codeforces1110G Tree-Tac-Toe

题面

题意

给出一棵树,初始有一些点被染成了白色而其他点没有颜色,现在有两个人A,B轮流操作,A会把某个未染色的点染成白色,B会把某个未染色的点染成黑色,若出现了一条长度为三,颜色相同的链,则对应颜色的人获胜,A先操作,请问哪一方会获胜。

做法

首先我们考虑转化一下初始为白色的节点,若点A为白色,则我们可以新建点B,C,D,并且连边(A-B),(B-C),(B-D),并将A变为未染色的点,不难发现两者等价,现在考虑如何处理没有点被染色的情况。
可以分成以下三种情况:
1.某个点的度数大于等于4,很显然,只要先手染这个点即可获胜。
2.某个点的度数为3,且有两个儿子不是叶子节点,同样先手必胜。
3.有两个点的度数为3,则若这两个点的距离为偶数,则先手必胜。先手只要先将这两个节点的父亲(唯一一个非叶子节点)染白,然后在这两条链上隔一个点染一下即可。
其余情况均为平局,显然黑方不可能赢。

代码

#include<bits/stdc++.h>
#define N 2001000
using namespace std;

int T,n,mx,tt,ds[N];
char str[N];
vector<int>to[N];

inline void add(int u,int v)
{
    to[u].push_back(v);
    to[v].push_back(u);
    ds[u]++,ds[v]++;
}

int dfs(int now,int last,int fd)
{
    if(now==fd) return 0;
    int i,t,tmp;
    for(i=0;i<to[now].size();i++)
    {
	t=to[now][i];
	if(t==last) continue;
	tmp=dfs(t,now,fd);
	if(tmp!=-1) return tmp+1;
    }
    return -1;
}

inline bool work()
{
    int i,j,p,q,cnt=0;
    for(i=1;i<=n;i++)
    {
	if(ds[i]>=4) return 1;
	if(ds[i]==3)
	{
	    cnt++;
	    if(cnt==1) p=i;
	    else if(cnt==2) q=i;
	    int ct=0;
	    for(j=0;j<to[i].size();j++) if(ds[to[i][j]]>1) ct++;
	    if(ct>=2) return 1;
	}
    }
    if(cnt<2) return 0;
    return dfs(p,-1,q)%2==0;
}

int main()
{
    int i,j,p,q,t;
    cin>>T;
    while(T--)
    {
	scanf("%d",&n);
	tt=n;
	for(i=1;i<n;i++)
	{
	    scanf("%d%d",&p,&q);
	    add(p,q);
	}
	scanf("%s",str+1);
	for(i=1;i<=n;i++)
	{
	    if(str[i]=='W')
	    {
		t=++tt;
		add(i,t);
		add(t,++tt);
		add(t,++tt);
	    }
	}
	n=tt;
	puts(work()?"White":"Draw");
	for(i=1;i<=n;i++)
	{
	    ds[i]=0;
	    to[i].clear();
	}
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值