CSU1811: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
题意:给一棵树,每个点有一种颜色,问对于每一条边,删除这条边之后形成的两棵子树的相交颜色种数。

思路:启发式合并,维护每个子树的颜色及其数量,分别讨论颜色的“由无到有”和“由有到满”两种情况就行了。这题还能用莫队算法,留坑。

# include 
# include 
# include 
# include 
# define PII pair
using namespace std;
const int maxn = 1e5+30;
mapall, mp[maxn];
map::iterator it;
int sum[maxn], ans[maxn], col[maxn];
vectorg[maxn];
void dfs(int cur, int pre, int pid)
{
    for(int i=0; ifirst, num = it->second;
            if(!mp[cur].count(color))//无到有
            {
                if(num < all[color]) ++sum[pid];
                mp[cur][color] += num;
            }
            else//有到满
            {
                mp[cur][color] += num;
                if(mp[cur][color] == all[color]) --sum[pid];
            }
        }
    }
    if(!mp[cur].count(col[cur])) {if(++mp[cur][col[cur]] < all[col[cur]]) ++sum[pid];}
    else if(++mp[cur][col[cur]] == all[col[cur]]) --sum[pid];
    ans[pid] = sum[pid];
}
void init(int n)
{
    all.clear();
    for(int i=0; i<=n; ++i)
    {
        ans[i] = sum[i] = 0;
        mp[i].clear();
        g[i].clear();
    }
}
int main()
{
    int n, x;
    while(~scanf("%d",&n))
    {
        init(n);
        for(int i=1; i<=n; ++i)
        {
            scanf("%d",&col[i]);
            ++all[col[i]];
        }
        for(int i=1, u, v; i

你可能感兴趣的:(DFS)