CSU 1811 Tree Intersection

来源:互联网 发布:mac屏保设置不生效 编辑:程序博客网 时间:2024/05/22 16:47

题意:

一棵树,每个节点有一种颜色,现在删去一条边,求这个树分成两部分,这两部分的共有颜色个数。

分析:

枚举每一棵子树所有存在的颜色的节点个数,看看有没有超过这种颜色再整个树中的个数,就是答案。
就是一个子树的合并操作,合并并不需要每一个子树都建立一个节点,只需要找出不同颜色最多的那个子树,在这个子树上进行合并就可以了。这个样子每一次最多暴力了u.size()/2,那么总的复杂度就是o(nlogn)

代码:

#include <bits/stdc++.h>using namespace std;typedef pair <int,int>  PII;typedef vector <int>    VI;#define pb  push_back#define mp  make_pair#define fi  first#define se  secondconst int maxn = 100010;int n,c[maxn],rt[maxn],dp[maxn],ans[maxn],cnt[maxn];map <int,int> hs[maxn],edge[maxn];VI  g[maxn];void dfs(int u,int fa){    int id = u,sz = -1;    for(int i = 0;i < (int)g[u].size();++ i){        int v = g[u][i];        if(v == fa)     continue;        dfs(v,u);        if((int)hs[rt[v]].size() > sz)   id = v,sz = (int)hs[rt[v]].size();    }    rt[u] = rt[id]; dp[u] = dp[id];    id = rt[u];    if(hs[id][c[u]] == 0) ++ dp[u];    hs[id][c[u]] ++;    if(hs[id][c[u]] == cnt[c[u]])   -- dp[u];    for(int i = 0;i < (int)g[u].size();++ i){        int v = g[u][i];        if(v == fa || rt[v] == id)     continue;        map <int,int> :: iterator it;        for(it = hs[rt[v]].begin();it != hs[rt[v]].end();++ it){            if(hs[id][it->fi] == 0) ++ dp[u];            hs[id][it->fi] += it->se;            if(hs[id][it->fi] == cnt[it->fi])   -- dp[u];        }    }    //cout << u << " " << rt[u] << " " << dp[u] << endl;    if(fa != -1)    ans[edge[u][fa]] = dp[u];}int main(){    //freopen("test.in","r",stdin);    while(~scanf("%d",&n)){        memset(cnt,0,sizeof(cnt));        memset(dp,0,sizeof(dp));        for(int i = 1;i <= n;++ i)  scanf("%d",c+i),++ cnt[c[i]];        for(int i = 1;i <= n;++ i)  rt[i] = i;        for(int i = 1;i <= n;++ i)  hs[i].clear(),edge[i].clear(),g[i].clear();        for(int i = 1;i < n;++ i){            int u,v;    scanf("%d%d",&u,&v);            g[u].pb(v);     g[v].pb(u);            edge[u][v] = i; edge[v][u] = i;        }        dfs(1,-1);        for(int i = 1;i < n;++ i)   printf("%d\n",ans[i]);    }    return 0;}
0 0