[长链剖分] 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 }

 

posted @ 2019-07-13 22:46 BEYang_Z 阅读(...) 评论(...) 编辑 收藏