<br>c++
「已經快是嚴冬了,榕樹的葉子還沒落呢……」git
「榕樹是常綠樹,是看不到明顯的落葉季節的……」spa
「唉……想不到已經七年了呢。榕樹仍是當年的榕樹,你卻不是當年的你了……」code
「其實又有什麼是一成不變的呢,榕樹常綠,翠綠樹冠的宏觀永恆,是由無數細小樹葉的榮枯更迭組成的。在時間的流逝中一切都在不斷變化着呢……」get
「但你看這榕樹,日日如此,季季如此,年年如此,彷彿亙古不變般,盤根錯節,鬱鬱蔥蔥。我在想,或許成爲一棵樹更好吧,任時間從枝葉間流過,我只守這一片綠蔭就好。」it
「榕樹當然長久,但在這無限的時光裏,終歸是要湮滅於塵土的。與其像榕樹通常,植根於一方泥土中感覺年復一年的四季更替。倒不如在有限的時間裏看過儘量多的世界吧。再說了,榕樹雖生長緩慢,卻依舊會在每一年春天抽出一根新的枝條去向外探索的呢……」class
「真的嗎,榕樹在她漫長的一輩子裏,就是這樣往外一步步探索的嗎?」移動
「畢竟就算樹冠看起來一成不變,榕樹也會隨着時間週期變化,春天到了天然就是生長的時候了,她也應當作出對應的表現吧……」di
「相比於對季節更替作出本能的生長,我倒寧願相信,榕樹有一顆活躍的的,探索的心。」時間
「其實榕樹是有心的,榕樹剛剛種下的時候,心就在根的地方發芽了。之後每一年春天榕樹長出新枝條的時候,心就會向着新枝條的方向移動一點,這樣就能更靠近外面的世界了。你看這頭頂上的枝條,縱橫交錯,其實心已經在這枝杈間,移動了數十載了呢……」
「哇,也就是說,這密密麻麻的樹杈中的某個地方,藏着這棵榕樹的心嗎?」
「沒錯,但是要知道它在哪,就得另花一番功夫了……」
「呀,這時候想一想,一株樹仍是不如一我的好……好比你,要是這樣貼上去的話,就能聽到跳動的聲音呢……」
<br>
解題思路
先判斷最後可否到 $1$ 怎麼作,考慮每個節點不一樣兒子子樹的兩次操做會相互抵消,顯然移回當前節點剩下最少操做的方案必定是剩下若干來自最大兒子子樹的點,那麼只須要儘量消除最大兒子子樹便可。
令 $tot[u]$ 表示從 $u$ 子樹內從 $u$ 出發最後回到 $u$ ,最少剩餘的生長操做數量。 $$ \begin{cases} tot[u] = sz[u] \bmod 2, & sz[u]-sz[v]-1 \geq tot[v]+1 \ tot[u]=tot[v]+1-(sz[u]-tot[v]-1), &otherwise \end{cases} $$ 其中 $v$ 是 $u$ 的全部兒子中子樹大小最大的那個,考慮若是最大兒子內部消完剩下的東西能夠直接用其它兒子的子樹消掉,那麼答案就是 $sz[u] \bmod 2$ ,不然每個其它兒子子樹內的點都能和最大兒子剩下的東西消一下,直接減便可。
考慮一次性要求全部點的可行性怎麼作,考慮在移到 $u$ 時當前已經完成的操做必定是 $1-u$ 的路徑以及路徑上掛着的一些子樹,事實上必定存在一種策略可讓這些掛着的子樹互相消除,那麼問題就轉化成和判斷 $1$ 的可行性相似的問題,把 $1-x$ 路壓縮起來當作新根便可。
/*program by mangoyang*/ #include<bits/stdc++.h> #define inf (0x7f7f7f7f) #define Max(a, b) ((a) > (b) ? (a) : (b)) #define Min(a, b) ((a) < (b) ? (a) : (b)) typedef long long ll; using namespace std; template <class T> inline void read(T &x){ int ch = 0, f = 0; x = 0; for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1; for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48; if(f) x = -x; } const int N = 1000005; vector<int> g[N]; int sz[N], ms[N], tot[N], ans[N], n; inline void dfs(int u, int fa){ sz[u] = 1; for(int i = 0; i < (int) g[u].size(); i++){ int v = g[u][i]; if(v == fa) continue; dfs(v, u), sz[u] += sz[v]; if(sz[v] > sz[ms[u]]) ms[u] = v; } if(!ms[u]) return; if(tot[ms[u]] + 1 <= sz[u] - sz[ms[u]] - 1) tot[u] = ((sz[u] - 1) & 1); else tot[u] = tot[ms[u]] + 1 - (sz[u] - sz[ms[u]] - 1); } inline void dfs2(int u, int fa, int anc, int add){ int ms2 = 0; if(u > 1){ int size = sz[u] + add, mx; if(sz[ms[u]] > sz[anc]) mx = ms[u]; else mx = anc; if(tot[mx] + 1 <= size - sz[mx] - 1) ans[u] = ((size - 1) & 1); else ans[u] = tot[mx] + 1 - (size - sz[mx] - 1); } for(int i = 0; i < (int) g[u].size(); i++) if(g[u][i] != fa && g[u][i] != ms[u] && sz[g[u][i]] > sz[ms2]) ms2 = g[u][i]; for(int i = 0; i < (int) g[u].size(); i++){ int v = g[u][i], tmp = 0; if(v == fa) continue; if(v == ms[u]) tmp = sz[ms2] > sz[anc] ? ms2 : anc; else tmp = sz[ms[u]] > sz[anc] ? ms[u] : anc; dfs2(v, u, tmp, add + sz[u] - sz[v] - 1); } } int main(){ int T, type; read(type), read(T); while(T--){ read(n); for(int i = 1; i <= n; i++) g[i].clear(), sz[i] = tot[i] = ms[i] = ans[i] = 0; for(int i = 1, x, y; i < n; i++){ read(x), read(y); g[x].push_back(y), g[y].push_back(x); } dfs(1, 0); ans[1] = tot[1]; dfs2(1, 0, 0, 0); if(type == 3){ printf("%d\n", !ans[1]); continue; } for(int i = 1; i <= n; i++) putchar(!ans[i] ?'1':'0'); puts(""); } return 0; }