hdu6035 Colorful Tree 樹形dp 給定一棵樹,每個節點有一個顏色值。定義每條路徑的值為經過的節點的不同顏色數。求所有路徑的值和。
阿新 • • 發佈:2017-07-26
void 題意 iostream cnblogs 編號 emp php scanf http
/** 題目:hdu6035 Colorful Tree 鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 題意:給定一棵樹,每個節點有一個顏色值。定義每條路徑的值為經過的節點的不同顏色數。求所有路徑的值和。 思路:看題解後,才想出來的。樹形dp。 求所有路徑的值和 = 路徑條數*總顏色數(n*(n-1)*colors/2)-sigma(每種顏色沒有經過的路徑條數) 主要是求每種顏色沒有經過的路徑條數。 畫一棵樹,我直接用顏色值表示節點編號。 2 / 3 4 / / 1 3 2 / \ / \ / 4 5 4 5 3 5 12個點。 首先求顏色值為3的不經過的路徑條數x 樹上有三個3.很容易想到: x = 最左邊那個3下面的3個點構成的路徑條數(3*2/2=3)+中間的3的兩個子樹分別構成的路徑條數和(0) +最右邊的3的子樹的分別構成的路徑條數和(0) +(總節點數-所有的3為根的子樹節點數之和)*(總節點數-所有的以3為根的子樹節點數之和-1)/2 ; 所以size[i]表示以i為根的樹的節點數。 sum[i]在dfs過程中,,維護。。比如假設顏色為2.上圖。 那麽左子樹是根為3,右子樹是根為4. 那麽遞歸完左子樹之後,sum[2] = 0; 然後再遞歸完右子樹後sum[2] = 3;就是右下角的那個2為根的子樹的點數。 最終sum[i]表示所有以i顏色為根的子樹的所有節點數之和。 sum[2] = 12; sum[1] = 3; sum[4] = 8; sum[5] = 3; sum[3] = 8;*/ #include<iostream> #include<cstdio> #include<algorithm> #include<vector> #include<cstring> using namespace std; typedef long long LL; const int N = 2e5+100; int size[N]; int sum[N]; int col[N]; int vis[N]; int colors, n; LL cnt; vector<int> G[N]; void dfs(int r,intf) { int len = G[r].size(), temp = 0; size[r] = 1; if(sum[col[r]]!=0){ temp = sum[col[r]]; sum[col[r]] = 0; } for(int i = 0; i < len; i++){ int to = G[r][i]; if(to==f) continue; dfs(to,r); size[r] += size[to]; cnt += (LL)(size[to]-sum[col[r]])*(size[to]-sum[col[r]]-1)/2; sum[col[r]] = 0; } sum[col[r]] = size[r]+temp; } int main() { int cas = 1; while(scanf("%d",&n)==1) { memset(vis, 0, sizeof vis); memset(size, 0, sizeof size); memset(sum, 0, sizeof sum); colors = 0; for(int i = 1; i <= n; i++) G[i].clear(); for(int i = 1; i <= n; i++){ scanf("%d",&col[i]); if(vis[col[i]]==0){ colors++; } vis[col[i]] = 1; } int u, v; for(int i = 1; i <= n-1; i++){ scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } cnt = 0; dfs(1,-1); for(int i = 1; i <= n; i++){ if(vis[i]==0) continue; cnt += (LL)(n-sum[i])*(n-sum[i]-1)/2; } printf("Case #%d: %lld\n",cas++,(LL)n*(n-1)/2*colors-cnt); } return 0; }
hdu6035 Colorful Tree 樹形dp 給定一棵樹,每個節點有一個顏色值。定義每條路徑的值為經過的節點的不同顏色數。求所有路徑的值和。