CF1110G Tree-Tac-Toe 博弈論、構造
阿新 • • 發佈:2019-02-08
space ace force bcd line for 至少 main esp
傳送門
顯然在雙方絕頂聰明的情況下,黑色不可能贏
首先考慮樹上一個白色的點都沒有的情況:
1、如果樹上有一個點的度數\(\geq 4\),白色必贏,只需要第一次將這一個點染成白色,接著隨便染它的兩個鄰居就可以達成目標
2、如果樹上有一個點的度數\(=3\),且它所連的\(3\)個點之間至少有\(2\)個點不是葉子節點,白色必贏,只需要第一次染這一個點,第二次染它的一個非葉子鄰居,第三次就一定至少存在一個未被染色的點與這兩個相鄰。
那麽剩下的情況,樹的形態只會是下圖中的三種
但是還沒完(我以為到這裏就完了結果WA2被Tutorial點名)
最重要的3、如果樹的形態是上面的圖中最下面的那一種,而且總點數為奇數,那麽白色必贏
圖長下面這樣,中間的……省略的是一條鏈,編號從左往右遞增。
白色最開始染\(2\)號點,黑色如果染\(3\)號點白色直接染\(1\)號點,所以黑色必須染\(1\)號點。此時白色染\(4\)號點,黑色又只能染\(3\)號點……如是白色染到\(2N\)號點,黑色染\(2N-1\)號點之後,白色染\(2N+1\)號點,那麽最右邊就會有兩個未被染的點,白色就贏了
其余的情況顯然都是Draw的
然後考慮已經被染成白色的點的影響,最開始天真的我想直接各種特判過掉,結果WA14不曉得怎麽回事
我們已經考慮了樹上沒有被染成白色的點的所有情況,那麽能否將一個已經被染成白色的點等價為若幹未被染成白色的點?實際上是可以的
假設下圖中\(1\)號點在原樹上是一個白色點,那就在保留它原來的鄰居的基礎上給它額外連上三個點,連成下面的ABCD結構
可以發現,如果白色將\(A\)號點塗白,黑色一定會將\(B\)號點塗黑,這樣就相當於原樹上塗白一個點了。
#include<bits/stdc++.h> //This code is written by Itst using namespace std; inline int read(){ int a = 0; char c = getchar(); bool f = 0; while(!isdigit(c)){ if(c == ‘-‘) f = 1; c = getchar(); } while(isdigit(c)){ a = (a << 3) + (a << 1) + (c ^ ‘0‘); c = getchar(); } return f ? -a : a; } const int MAXN = 1e6 + 9; struct Edge{ int end , upEd; }Ed[MAXN << 1]; int head[MAXN] , in[MAXN] , N , cntEd , cnt; char s[MAXN]; inline void addEd(int a , int b){ Ed[++cntEd].end = b; Ed[cntEd].upEd = head[a]; head[a] = cntEd; ++in[a]; } int main(){ for(int T = read() ; T ; --T){ N = read(); cntEd = 0; memset(head , 0 , sizeof(int) * (N + 1)); memset(in , 0 , sizeof(int) * (N + 1)); for(int i = 1 ; i < N ; ++i){ int a = read() , b = read(); addEd(a , b); addEd(b , a); } scanf("%s" , s + 1); if(N < 3){ puts("Draw"); continue; } if(N == 3){ int cnt = 0; for(int i = 1 ; i <= N ; ++i) cnt += s[i] == ‘W‘; puts(cnt >= 2 ? "White" : "Draw"); continue; } bool ifans = 0; int cnt1 = 0; for(int i = 1 ; i <= N ; ++i) if(s[i] == ‘W‘){ addEd(i , ++N); head[N] = 0; addEd(N , i); in[N] = 3; } for(int i = 1 ; !ifans && i <= N ; ++i) if(in[i] > 3) ifans = 1; else if(in[i] == 3){ int cnt = 0; for(int j = head[i] ; j ; j = Ed[j].upEd) cnt += in[Ed[j].end] >= 2; ifans = cnt >= 2; ++cnt1; } if(cnt1 == 2 && (N & 1)) ifans = 1; puts(ifans ? "White" : "Draw"); } return 0; }
CF1110G Tree-Tac-Toe 博弈論、構造