[长链剖分] Uoj #139 被删除的黑白树
题目大意
- 给出一棵有根树,要求对尽量多的节点染色,使得每个叶节点到根的路径上的染色节点数都相等
- 𝑛≤100000
题解
-
设f[i,j]表示以i为根的子树中每个叶节点到i路径上的染色点数恰好为j时的答案
-
用长链剖分优化转移就是O(n)
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 using namespace std; 5 const int N=100010; 6 int n,cnt,sz,ans,head[N],nx[N],deep[N],son[N],h[N],t[N],w[N]; 7 struct edge{int to,from;}e[N*2]; 8 void insert(int x,int y) 9 { 10 e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt; 11 e[++cnt].to=x,e[cnt].from=head[y],head[y]=cnt; 12 } 13 void dfs1(int x,int fa) 14 { 15 for (int i=head[x];i;i=e[i].from) 16 if (e[i].to!=fa) 17 { 18 dfs1(e[i].to,x); 19 if (deep[e[i].to]>deep[son[x]]) son[x]=e[i].to; 20 } 21 deep[x]=deep[son[x]]+1; 22 } 23 void dfs2(int x,int fa) 24 { 25 if (son[x]) dfs2(son[x],x),h[x]=h[son[x]],t[x]=t[son[x]]; 26 for (int i=head[x];i;i=e[i].from) 27 if (e[i].to!=fa&&e[i].to!=son[x]) 28 { 29 dfs2(e[i].to,x); 30 int k=h[x],ls=0; 31 for (int j=h[e[i].to];j&&k;j=nx[j],ls=k,k=nx[k]) w[k]+=w[j]; 32 nx[ls]=0;t[x]=ls; 33 } 34 if (son[x]) nx[t[x]]=++sz,w[sz]=w[t[x]]+1,t[x]=sz; else h[x]=t[x]=++sz,w[sz]=1; 35 } 36 int main() 37 { 38 scanf("%d",&n); 39 for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),insert(x,y); 40 dfs1(1,0),dfs2(1,0); 41 for (int i=h[1];i;i=nx[i]) ans=max(ans,w[i]); 42 printf("%d",ans); 43 }