题解:CF1110G Tree-Tac-Toe
不难发现,黑方不可能胜利。由于只染色三个连点就胜利,而白方不仅先手还提前有白点,因此白方每染色一步,黑方都需要尽可能牵制白方,导致自己不可能获胜。
先从简单的情况入手,考虑初始没有白点的情况。难以发现,有以下四种情况(此外,每一种情况都不能满足前面的情况)。
:::info[情况一]{open}
存在一个点的度数大于
白方染色
:::
:::info[情况二]{open}
存在一个点度数为
白方染色
:::
:::info[情况三]{open}
对于任意一个度数为
白方染色
:::
:::info[情况四]{open}
不存在或有且仅有一个度数为
:::
现在考虑初始的白点。如果影响到了以上四种情况,那不坏菜了?所以应尽可能地让初始的白点不影响以上四种情况。
对于初始白点
那么,初始白点可以视为是初始无色,白方染色
注意,由于每次添加
四种情况的时间复杂度都是
const int N=2000005;
int n,m,du[N];
int tot,ver[N<<1],nxt[N<<1],head[N];
inline void add(int x,int y){ver[++tot]=y,nxt[tot]=head[x],head[x]=tot;}
inline void add_edge(int x,int y){du[x]++,du[y]++,add(x,y),add(y,x);}
char s[N];
inline bool check1()
{
for(int i=1;i<=n;i++) if(du[i]>3) return true;
return false;
}
inline bool check2()
{
for(int x=1;x<=n;x++)
{
if(du[x]==3)
{
int cnt=0;
for(int i=head[x];i;i=nxt[i]) if(du[ver[i]]>1) cnt++;
if(cnt>1) return true;
}
}
return false;
}
int dis[N];
void dfs(int x,int fa)
{
dis[x]=dis[fa]+1;
for(int i=head[x];i;i=nxt[i]) if(ver[i]!=fa) dfs(ver[i],x);
}
inline bool check3()
{
int a=0,b=0;
for(int i=1;i<=n;i++)
if(du[i]==3)
{
if(!a) a=i;
else b=i;
}
if(!b) return false;
for(int i=1;i<=n;i++) dis[i]=0;
dfs(a,0);
if(dis[b]&1) return true;
else return false;
}
inline void solve()
{
n=m=read(),tot=0;
for(int i=1;i<n;i++)
{
int x=read(),y=read();
add_edge(x,y);
}
scanf("%s",s+1);
for(int i=1;i<=n;i++)
if(s[i]=='W')
{
add_edge(i,m+1);
add_edge(m+1,m+2);
add_edge(m+1,m+3);
m+=3;
}
n=m;
if(check1()||check2()||check3()) puts("White");
else puts("Draw");
for(int i=1;i<=n;i++) du[i]=head[i]=0;
}
int main()
{
for(int T=read();T;T--) solve();
return 0;
}
话说为什么洛谷题解在无序列表后面加了图片后,不能继续保持原本的 Tab 啊,只能用折叠框了,跪求管理员大大通过。