Atcoder Beginner Contest 209 E Shiritori

Atcoder Beginner Contest 209 E Shiritori

题目链接:https://atcoder.jp/contests/abc209/tasks/abc209_e

? 很容易想到这是一幅图。我们将每个单词的前三个字母向后三个字母连一条边。然后就构成了一幅有向的图。对于这幅图来说,如果一个人走到了一个没有出度的点,那么他就赢了,因为另一个人不能再说出任何一个单词(走到另外一个点)。我们用一个 \(dp\) 数组表示从这个点开始游戏的输赢情况,0 表示平局,1 表示 Takahashi 赢,2 表示 Aoki 赢。那么显然,所有出度为 0 的点的 \(dp\) 值都为1。

? 现在我们考虑 \(dp\) 数组的转移。如果一个点所有能走到的点当中,有一个点的 \(dp\) 值为 1。那么这个点的 \(dp\)肯定为 2。因为 Aoki 只要往这个点上走,那么他就赢了。如果这个点能到达的所有点的 \(dp\) 值为 2,那么这个点的 \(dp\) 值才能为 1。如果一个点不符合上述的两种情况,那么它的 \(dp\) 值就是 0 了,因为能更新状态为 1,2,的只有上述两种情况,然后这个点一定是 0,1,2 中的一个,只有可能是 0了。

? 然后我们反向连边,将所有入度为 0 的点的 \(dp\) 值设置为 1。然后跑一趟拓扑排序就好了。当然,这里的拓扑排序要魔改一下,如果一个点的 \(dp\) 值被确定为 1 或 2 了,可以立马扔进队列中,因为根据我们上面的转移,它不可能再被更改了。这样操作可以让拓扑排序渗透到一些环中。对于一些环来说,环的某一部分是可以被更新到的,一部分又是无法被更新到的,而可以被更新到的点中它们被更新的状态是不同的,简而言之,一个环中所有点的 \(dp\) 值是不同的,所以我们不能缩点进行拓扑,而是直接进行拓扑,对于更新不到的点,那么就是平局了。建议手搓几组样例更好的理解(文笔不好,讲不清楚

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e5+5;
int n,dp[MAXN],in[MAXN],tot,p[MAXN];
char s[10];
map <string,int> mp;
vector <int> edge[MAXN];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
	{
		scanf("%s",s+1);
		int len=strlen(s+1);
		string u="",v="";
		for(int j=1;j<=3;++j) u+=s[j];
		for(int j=len-2;j<=len;++j) v+=s[j];
		if(!mp.count(u)) mp[u]=++tot;
		if(!mp.count(v)) mp[v]=++tot;
		p[i]=mp[v];in[mp[u]]++;
		edge[mp[v]].push_back(mp[u]);
	}
	queue <int> q;	
	for(int i=1;i<=tot;++i)
	{
		if(!in[i])
		{
			dp[i]=1;
			q.push(i);
		}
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		for(int i=0;i<edge[now].size();++i)
		{
			int to=edge[now][i];
			if(dp[to]==0)
			{
				in[to]--;
				if(dp[now]==1) dp[to]=2,q.push(to);
				else if(in[to]==0)
				{
					dp[to]=1;
					q.push(to);
				}
			}
		}
	}
	for(int i=1;i<=n;++i)
	{
		if(dp[p[i]]==1) printf("Takahashi\n");
		else if(dp[p[i]]==2) printf("Aoki\n");
		else printf("Draw\n");
	}
}

? 像这种题目,平局的转移不好判定,那么我们将另外两种判定出来,其他情况就是平局了。换句话说,如果一个集合的子集不好求,我们可以求这个子集的补集,从而得到这个子集。这在某些题目中也是一种优秀的方法。

Atcoder Beginner Contest 209 E Shiritori

上一篇:UML类图


下一篇:JZOJ 3423.Vani和Cl2捉迷藏 & [CTSC2008]祭祀