CF1442E Black, White and Grey Tree 題解
阿新 • • 發佈:2021-11-08
Link.
Description.
給定一個樹,每個點顏色可能是黑、白、灰。
你每次選擇一個聯通塊,在裡面選擇若干個點,然後刪去它和它們的邊。
同時,你不能同時選擇白點和黑點,問至少多少次刪完。
Solution.
首先考慮沒有灰點的問題。
設一條邊的權值 \(w=[c_u\ne c_v]\),答案就是 \(\left\lceil\frac {len}2\right\rceil+1\),其中 \(len\) 表示帶權直徑。
然後考慮灰點可以被當作任意顏色。
就可以直接樹型 dp 求最短直徑。
考慮設 \(f_{u,0/1}\) 表示 \(u\) 為根到葉子的最長路。
\(g_{u,0/1}\)
答案就是 \(\max_{u}(\min(g_{u,0},g_{u,1}))\)。
直接轉移就行了?
注意最大值最小值要搞清楚
Coding.
點選檢視程式碼
//Coded by Kamiyama_Shiki on 2021.11.08 {{{ //是啊……你就是那隻鬼了……所以被你碰到以後,就輪到我變成鬼了 #include<bits/stdc++.h> using namespace std;typedef long long ll; template<typename T>inline void read(T &x) { x=0;char c=getchar(),f=0; for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1; for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48); f?x=-x:x; } template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}} const int N=200005;int n,a[N],rs=0,f[N][2],g[N][2]; struct edge{int to,nxt;}e[N<<1];int et,head[N]; inline void adde(int x,int y) {e[++et]=(edge){y,head[x]},head[x]=et;} inline void dfs(int x,int fa) { if(a[x]==3) g[x][0]=g[x][1]=-1e7,f[x][0]=f[x][1]=0; else g[x][a[x]&1]=-1e7,f[x][a[x]&1]=0,g[x][(a[x]&1)^1]=f[x][(a[x]&1)^1]=1e7; for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa) { int y=e[i].to,vl;dfs(y,x); if(a[x]&2) vl=min(f[y][0],f[y][1]+1),g[x][0]=max(g[x][0],f[x][0]+vl),f[x][0]=max(f[x][0],vl); if(a[x]&1) vl=min(f[y][1],f[y][0]+1),g[x][1]=max(g[x][1],f[x][1]+vl),f[x][1]=max(f[x][1],vl); }rs=max(rs,min(g[x][0],g[x][1])); //printf("%d %d ( %d %d )\n",g[x][0],g[x][1],f[x][0],f[x][1]); } inline void solve() { read(n),rs=0,et=0;for(int i=1;i<=n;i++) head[i]=0; for(int i=1;i<=n;i++) read(a[i]),a[i]=3^a[i]; for(int i=1,x,y;i<n;i++) read(x,y),adde(x,y),adde(y,x); dfs(1,0),printf("%d\n",(rs+1)/2+1); } int main() {int Ca;for(read(Ca);Ca--;) solve();return 0;}