Codeforces 110G Tree-Tac-Toe

题目

https://codeforces.com/contest/1110/problem/G

题目大意

给你一棵树,树上的节点有的是白色,有的是无色。接着有两个操控白色和黑色的人进行游戏,按白、黑、白、黑的顺序依次操作,每次操作可以将一个无色的节点染成自己的颜色。如果出现了一条含3个节点的同色路径,那么操控那种颜色的人胜利。若到无法操作时仍未决出胜负,则是平局。
有T组询问 ( 1 ≤ T ≤ 50000 ) (1≤T≤50000) (1T50000),树的节点个数为n ( 1 ≤ n ≤ 5 ⋅ 1 0 5 ) (1≤n≤5⋅10^5) (1n5105)

题解

一开始我发现了几个结论:

  1. 黑色不可能赢。因为一开始白色方是有优势的,如果黑色能赢,那么白色按照它的下法来操作必定能赢;
  2. 只用考虑初始图中是否含有白色必胜的子图即可。

然后我就开始分类讨论,结果发现既要考虑白色点,又要考虑无色点,提交之后发现漏考虑的情况一个接一个。于是索性放弃,手动模拟了好多个数据后,发现一个白色点等价于一个连接一个 有2个无色点儿子的无色点儿子 的无色点(懒得画图)。
接着白色必胜的情况就只有3种了:

  1. 存在度数大于等于4的节点;
  2. 存在连接至少2个度数大于等于2的点额外的1个点的点;
  3. 不符合以上两种情况,且拥有两个度数大于等于3的点的连通图,要求这两个点之间的最短路径的边数为偶数。

于是就AC了。

CODE

#include<cstdio>
using namespace std;
#define win {white=1;goto print;}
#define M 2000005
int deg1[M],deg2[M],x[M],y[M],fir[M],to[4000005],nex[4000005],data[M],cnt,s;
char c[500005];bool dis[M],vis[M];
inline void bfs(int k)
{
    
    
	for(int i=1;i<=cnt;++i) dis[i]=vis[i]=0;
	int head=0,tail=1,u,v;
	data[1]=k,vis[k]=1;
	while(head<tail)
	{
    
    
		u=data[++head];
		for(int i=fir[u];i;i=nex[i]) if(!vis[to[i]])
		{
    
    
			v=to[i];
			dis[v]=dis[u]^1;
			data[++tail]=v;
			vis[v]=1;
		}
	}
}
inline void inc(int x,int y)
{
    
    
	to[++s]=y,nex[s]=fir[x],fir[x]=s;
	to[++s]=x,nex[s]=fir[y],fir[y]=s;
}
int main()
{
    
    
	int t,n,m,i,j,u,v;bool white,flag;
	scanf("%d",&t);
	for(j=1;j<=t;++j)
	{
    
    
		scanf("%d",&n),m=n-1,cnt=n;
		u=v=0,white=0,flag=1;
		for(i=1;i<=n;++i) deg1[i]=deg2[i]=fir[i]=0;
		for(i=1;i<n;++i) scanf("%d%d",x+i,y+i),inc(x[i],y[i]);
		scanf("%s",c+1);
		for(i=1;i<=n;++i) if(c[i]=='W')
		{
    
    
			fir[cnt+1]=fir[cnt+2]=fir[cnt+3]=0;
			deg1[cnt+1]=deg1[cnt+2]=deg1[cnt+3]=0;
			deg2[cnt+1]=deg2[cnt+2]=deg2[cnt+3]=0;
			x[++m]=i,y[m]=cnt+1,inc(i,cnt+1);
			x[++m]=cnt+1,y[m]=cnt+2,inc(cnt+1,cnt+2);
			x[++m]=cnt+1,y[m]=cnt+3,inc(cnt+1,cnt+3);
			cnt+=3;
		}
		for(i=1;i<=m;++i) ++deg1[x[i]],++deg1[y[i]];
		for(i=1;i<=m;++i)
		{
    
    
			if(deg1[x[i]]>1) ++deg2[y[i]];
			if(deg1[y[i]]>1) ++deg2[x[i]];
		}
		for(i=1;i<=cnt;++i)
		{
    
    
			if(deg1[i]==3)
			{
    
    
				if(!u) u=i;
				else if(!v) v=i;
				else flag=0;
			}
			if(deg1[i]>3) win
			if(deg1[i]>2&&deg2[i]>1) win
		}
		if(flag&&u&&v) bfs(u),white=!dis[v];
		print:puts(white?"White":"Draw");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/huangzihaoal/article/details/108651942