Rollback tree DP (dfs order by dp) - hdu6035

Earlier in this topic are operating in another blog. The difficulty lies in the contribution of color ci, how to find the answer to a dfs

Consider first how to separately color a i is calculated in the dfs

  Using dfs traversal order manner, in a deep searching process, the hit point with the color i u, u each color are not child node v i is the contribution of a link block,

  V contribution Unicom block size is size [v] -sum {v of the highest level to the node i is the color of the subtree rooted size}

  Then we must first obtain the highest level of color to the node i is the size of the subtree rooted in v, it represents the size of all sub-trees so far with color i sum, with last able to save v enter sum before dfs, i.e., when the sum is not lower subtree v i of color

  Go to v dfs, and then added to the size of the subtrees in the sum

  After all subtrees v been traversed, we will find that the total sum-last node is the highest in the color i is the size of the subtree rooted at level v

  Then v contribute Unicom block size is k = size [v] - (sum-last)

  Then the subtree of u to v 'perform the same operation until completed through all subtrees of u, at this time has become a sum up to u (u is not included) in the color i is the size of the subtree rooted with

  To calculate u i ancestor of color, you need to u is also incorporated in sum, then u only need to add your own in the sum, plus Unicom block all contributed to v

  Information has now completed all of the information maintenance, u can launch the dfs, determined to roll back up u ancestor node

Again consider how to calculate all the colors that appear in the first dfs,

  We can be found in the above recursion, each color in demand contributed only used the size [], as well as each color corresponding to the sum, then use the [c] array sum to maintain the color of the representative of the sum to c, you can maintenance contribute in a variety of colors in dfs

This question and imaginary tree somewhat similar places, first as each color is a challenge, it is similar to the virtual tree asked

Then the process is rolled back to dfs from the leaves up demand (in fact, according to dfs order) by: recording into the state before the first time encountered when u dfs, dfs state and processes all of its child nodes and then to calculate u status

#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define maxn 200005 
#define ll long long

ll ans,color[maxn],size[maxn],sum[maxn];
vector<int>G[maxn];

void dfs1(int u,int pre){
    size[u]=1;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==pre)continue;
        dfs1(v,u);
        size [U]+=size [V]; 
    } 
} 

// This is the most important tree dp understanding SUM [] array meaning, edging sum [x] updating the virtual image is from the same tree leaf node up rollback 
 void DFS2 ( int u, int pre) { 
    LL OTHER = 0 ; // OTHER size is expressed as [u] u all subtracted at the highest Color [u] is the size of the root 
    for ( int I = 0 ; I <G [u] .size (); I ++ ) {
         int V = G [u] [I];
         IF (V == pre) Continue ; 
        LL Last = SUM [color [u]]; // record before the front of the sub-tree color u subtree (virtual tree) the value in 
        DFS2 (V, U); 
        LL the diffSUM = [color [u]] - Last; // ) G [i] .clear ();v is the color sub-tree color [u] is the number of
         // size of block Unicom v tree does not include color [u] of 
        ANS + = (size [v] -diff- . 1 ) * (size [v] -diff ) / 2 ; 
        OTHER + = size [V] - the diff; 
    } 
    SUM [Color [u]] + = OTHER + . 1 ; // + 1'd itself because u Color [u] 
}
 int F [MAXN], TOT;
 int main () { 
    LL n-, T = 0 ;
     the while (CIN >> n-) {
         ++ T;
         for ( int I = . 1 ; I <= n-; I ++ 
        Memset (F, 0 ,sizeof f);
        tot=0;
        
        for(int i=1;i<=n;i++){
            scanf("%d",&color[i]);
            f[color[i]]=1;
        }
        for(int i=1;i<=n;i++)tot+=f[i];
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }        
        
        if(tot==1){
            printf("Case #%d: %lld\n",t,n*(n-1)/2);
            continue;
        }
        
        memset(size,0,sizeof size);
        memset(sum,0,sizeof sum);
        
        ans=0;
        dfs1(1,1);dfs2(1,1);
        for(int i=1;i<=n;i++)
            if(f[i])
                ans+=(n-sum[i])*(n-sum[i]-1)/2;
        ll tmp=(n-1)*n/2*tot;
        printf("Case #%d: %lld\n",t,tmp-ans);
        
    }
}

 

Guess you like

Origin www.cnblogs.com/zsben991126/p/11200539.html