CSUOJ1811 Tree Intersection (启发式合并)
Bobo has a tree with n vertices numbered by 1,2,…,n and (n-1) edges. The i-th vertex has color c
i, and the i-th edge connects vertices a
i and b
i.
Let C(x,y) denotes the set of colors in subtree rooted at vertex x deleting edge (x,y).
Bobo would like to know R_i which is the size of intersection of C(a
i,b
i) and C(b
i,a
i) for all 1≤i≤(n-1). (i.e. |C(a
i,b
i)∩C(b
i,a
i)|)
Input
The input contains at most 15 sets. For each set:
The first line contains an integer n (2≤n≤10
5).
The second line contains n integers c
1,c
2,…,c
n (1≤c_i≤n).
The i-th of the last (n-1) lines contains 2 integers a
i,b
i (1≤a
i,b
i≤n).
OutputFor each set, (n-1) integers R 1,R 2,…,R n-1.Sample Input
4 1 2 2 1 1 2 2 3 3 4 5 1 1 2 1 2 1 3 2 3 3 5 4 5
Sample Output
1 2 1 1 1 2 1
Hint
题解:题意就是,给以一颗树n个节点,每个节点有一种颜色,然年后对于n-1条边,如果把一条边截断,让你求两颗子树有多少种相同的颜色,依次输入每一条边的答案。
启发式搜索,分别记录点和边的答案;如果点u和其子树某种颜色的数量已经等于总量了,那么对于该子树外的一部分,就没有该中颜色了,答案-1;如果小于总量,答案+1;
然后更新u节点该颜色的数量即可;
参考代码:
![](http://img.e-com-net.com/image/info8/b8d97b5613f94ed2ba791cad57d0b2ed.gif)
![](http://img.e-com-net.com/image/info8/2f88dd3f1cd145f59c0e47b51acdbd4b.gif)
1 #include2 using namespace std; 3 #define clr(a,val) memset(a,val,sizeof (a)) 4 #define pb push_back 5 #define fi first 6 #define se second 7 typedef long long ll; 8 const int maxn=1e5+10; 9 inline int read() 10 { 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} 13 while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 struct Edge{ 17 int to,index,nxt; 18 } edge[maxn<<1]; 19 int n,head[maxn<<1],tot; 20 int col[maxn],sum[maxn],ans[maxn],res[maxn<<1];//ans[u]表示u点及子节点的答案, res[edge]表示边的答案 21 map<int,int> cnt[maxn];//cnt[u][color] 表示u点子树color颜色有多少个节点 22 23 inline void Init() 24 { 25 clr(head,-1);clr(sum,0); tot=0; 26 for(int i=0;i<=n;++i) cnt[i].clear(); 27 } 28 29 inline void addedge(int u,int v,int id) 30 { 31 edge[tot].to=v; 32 edge[tot].index=id; 33 edge[tot].nxt=head[u]; 34 head[u]=tot++; 35 } 36 37 inline void dfs(int u,int fa,int id) 38 { 39 cnt[u][col[u]]=1; 40 ans[u] = cnt[u][col[u]] 1:0; 41 for(int e=head[u];~e;e=edge[e].nxt) 42 { 43 int v=edge[e].to; 44 if(v==fa) continue; 45 dfs(v,u,edge[e].index); 46 if(cnt[u].size()<cnt[v].size()) 47 { 48 swap(cnt[u],cnt[v]); 49 swap(ans[u],ans[v]); 50 } 51 map<int,int>::iterator it; 52 for(it=cnt[v].begin();it!=cnt[v].end();it++) 53 { 54 if(!cnt[u][(*it).fi] && (*it).se ans[u]; 55 else if(cnt[u][(*it).fi] && cnt[u][(*it).fi]+(*it).se==sum[(*it).fi]) --ans[u]; 56 cnt[u][(*it).fi]+=(*it).se;//加上子树的数量 57 } 58 } 59 res[id]=ans[u]; 60 } 61 62 int main() 63 { 64 while(~scanf("%d",&n)) 65 { 66 Init(); 67 for(int i=1;i<=n;++i) col[i]=read(),sum[col[i]]++; 68 for(int i=1;i i) 69 { 70 int u=read(),v=read(); 71 addedge(u,v,i);addedge(v,u,i); 72 } 73 dfs(1,0,0); 74 for(int i=1;i "%d\n",res[i]); 75 } 76 77 return 0; 78 }
posted @
2019-01-19 21:34 SongHL 阅读(
...) 评论(
...) 编辑 收藏