Codeforces Global Round 1 G.tree-tac-toe

题目大意

链接
Codeforces Global Round 1 G.tree-tac-toe_第1张图片

题目大意

给你一颗树,然后上面有某些节点染了白色,其余的无色。
现在有两个人,两个人轮流染色。一个染白色,另一个人染黑色。
他们可以选择任意一个没有染色的点染色。如果最先有个人染的色有三个点连在一起,那么就胜出。
问谁必胜或平局。
要求 O ( n ) O(n) O(n)

思考历程

真是一道神仙题。
一开始没有什么思路,然后手玩了一下样例也是没有思路。
然后想想不染色的情况。
然后就发现了三种情况(其中一种还是错的)
接下来染色的也没有什么好想法。
于是与lvle大爷疯狂讨论。
lvle大爷非常轻松地把这种情况给讨论出来了,其实就是链。
总结了几种小情况,然后就开码。
前后码了两次,然后再手玩很多小数据,还翻了翻英文题解发现不染色的情况还是讨论错了。最后终于是过了。

题解

当然黑不可能胜出(壕无人性)
先考虑不染色的情况:

  • 1、当某个点的度数大于等于4时,白必胜。

  • 2、当某个点度数为3时,那么就看他连接的三个儿子。若其中有两个儿子有另外再多伸出一个儿子(度数大于等于2),那么白必胜。

  • 3、当某个点度数为2时,那么他只可能长下面这种情况。然后判断“若干个点”是否是奇数个点即可。
    Codeforces Global Round 1 G.tree-tac-toe_第2张图片
    然后染色情况:

  • 若染色点大于等于3,则白必胜(可以归纳到上面的不染色情况)

  • 若染色点的度数大于1,则白必胜(特判一下n=3的情况)

  • 若两个染色点连在一起,则白必胜

  • 接下来有三种情况:

  • Codeforces Global Round 1 G.tree-tac-toe_第3张图片
    Codeforces Global Round 1 G.tree-tac-toe_第4张图片
    Codeforces Global Round 1 G.tree-tac-toe_第5张图片

情况是真滴多,调了好久。

然后就应该没啦

代码

#include 
#include 
#include 
#include 
using namespace std;
const int maxn=500010;
 
int tot,las[maxn*2],tov[maxn*2],nex[maxn*2],rd[maxn],n,x[maxn],y[maxn];
char s[maxn];
 
void insert(int x,int y)
{
     
	tot++;
	tov[tot]=y;
	nex[tot]=las[x];
	las[x]=tot;
}
 
int main()
{
     
	int T,n;
	scanf("%d",&T);
	while (T--)
	{
     
		scanf("%d",&n);
		tot=0;
		for (int i=1;i<=2*n;i++)
		{
     
			las[i]=0;
		}
		for (int i=1;i<=n;i++)
		{
     
			rd[i]=0;
		}
		for (int i=1;i<n;i++)
		{
     
			scanf("%d%d",&x[i],&y[i]);
			insert(x[i],y[i]);
			insert(y[i],x[i]);
			rd[x[i]]++;
			rd[y[i]]++;
		}
		scanf("%s",s+1);
		bool bz=true;
		bool pd=true;
		int gs=0;
		for (int i=1;i<=n;i++)
		{
     
			if (s[i]=='W')
			{
     
				pd=false;
				gs++;
			}
		} 
		
//		if (pd)
//		{
     
		int cnt=0;
		for (int i=1;i<=n;i++)
		{
     
			if (rd[i]>=4)
			{
     
				bz=false;
				break;
			}
			int k=0;
			if (rd[i]==3)
			{
     
				cnt++;
				for (int j=las[i];j;j=nex[j])
				{
     
					if (rd[tov[j]]>=2) k++;
				}
			}
			if (k>=2)
			{
     
				bz=false;
				break;
			}
			k=0;
			if (rd[i]==2)
			{
     
				for (int j=las[i];j;j=nex[j])
				{
     
					if (rd[tov[j]]==3) k++;
				}
			}
			if (k>=2)
			{
     
				bz=false;
				break;
			}
		}
		if (cnt==2)
		{
     
			if ((n-6)%2==1)
			{
     
				printf("White\n");
				continue;
			}
		}
		if (!bz) 
		{
     
			printf("White\n");
			continue;
		}
		if (n==3)
		{
     
			if (gs>=2)
			{
     
				printf("White\n");
				continue;
			}
			else
			{
     
				printf("Draw\n");
				continue;
			}
		}
//		}
		if (!pd)
		{
     
			if (gs>2)
			{
     
				printf("White\n");
				continue;
			}
			bool pp=false;
			for (int i=1;i<=n;i++)
			{
     
				if (s[i]=='W' && rd[i]>=2)
				{
     
					bz=false;
					break;
				}
				if (s[i]=='W')
				{
     
					bool op=true;
					for (int j=las[i];j;j=nex[j])
					{
     
						if (s[tov[j]]=='W' || rd[tov[j]]>2)
						{
     
							op=false;
							break;
						}
					}
					if (!op)
					{
     
						bz=false;
						break;
					}
				}
				if (rd[i]==3)
				{
     
					pp=true;
				}
			}
			if (!bz)
			{
     
				printf("White\n");
				continue;
			}
			if (gs==1)
			{
     
				if (n%2==0 && pp)
				{
     
					printf("White\n");
					continue;
				}
			}
			if (gs==2)
			{
     
				if (n%2==1)
				{
     
					printf("White\n");
					continue;
				}
			}
		}
		printf("Draw\n");
	}
} 

你可能感兴趣的:(CodeForces)