767C Garland (樹形dp經典入門,dfs實現)
阿新 • • 發佈:2018-12-24
連結: http://codeforces.com/problemset/problem/767/C
題意:每顆樹有一個權值,問如何分子樹能把它分成相等權重的三部分
思路:sum求和,只有sum是能夠被3整除的才能被被分。然後從下到上dfs出每個結點的子樹和(包含自己),bfs後通過兩個flag,來記錄是否能夠分成相等的3部分:(找到一部分,優先用flag1表示)
1.如果flag1=0並且當前遍歷到的子樹符合條件,則:flag1=當前這個結點的編號,同時設當前子樹的和為0
2.如果flag2=0並且當前遍歷到的子樹符合條件,則:flag2=當前的結點編號,同時設當前子樹的和為,且不是根節點
(注意這個時候:要求並且當前結點不是根節點的情況,比如: )
該情況下是不符合情況的
程式碼:
#include<cstdio> #include<vector> #include<string.h> #include<algorithm> using namespace std; const int maxn=1000006; vector<int>v[maxn]; int n; int flag1=0,flag2=0; int fa[maxn]; int val[maxn]; int dp[maxn]; int sum; int rt; void dfs(int root){ for(int i=0;i<v[root].size ();i++){ int temp=v[root][i]; dfs(temp); dp[root]+=dp[temp]; } if(flag1==0&&dp[root]==sum/3){ flag1=root; dp[root]=0; }else if(flag2==0&&dp[root]==sum/3){ flag2=root; dp[root]=0; }if(flag1&&flag2){ return ; } } int main(){ int n; scanf("%d",&n); memset(fa,-1,sizeof(fa)); for(int i=1;i<=n;i++){ int x,y; scanf("%d%d",&x,&y); fa[i]=x; if(x)v[x].push_back (i); dp[i]=y; sum+=y; if(!x)rt=i; } if(sum%3){ printf("-1\n"); return 0; } dfs(rt); if(flag1&&flag2){ printf("%d %d\n",flag1,flag2); }else printf("-1\n"); }