http://codeforces.com/problemset/problem/767/C
一棵树,每个节点有一个权值t,把它分成三部分,每部分要求权值和相等。
由于子树的子树里再出现等于sum/3的情况,那么dp[u]=0,就可以很好的避免计算情况了
dfs 第一找出来一个sum/3,然后子树结果清零,然后再dfs一次,直接忽视掉前一个sum/3,找出第二个sum/3,如果能找出来就输出,不能就-1。
还有一种笨写法。(傻逼的我调了半辈子)
代码一:
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define MS(a) memset(a,0,sizeof(a)) #define MP make_pair #define PB push_back const int INF = 0x3f3f3f3f; const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } ////////////////////////////////////////////////////////////////////////// const int maxn = 1e5+10; int n,s,x,dp[maxn],ans1,ans2,sum; vector<int> g[maxn]; void dfs(int u){ for(int i=0; i<(int)g[u].size(); i++){ dfs(g[u][i]); dp[u] += dp[g[u][i]]; } if(dp[u]==sum/3 && u!=s){ if(!ans1) { ans1=u; dp[u]=0;} else if(!ans2) { ans2=u; return ;} } } int main() { cin >> n; sum = 0; for(int i=1; i<=n; i++){ scanf("%d%d",&x,&dp[i]); if(x==0) s = i; else g[x].push_back(i); sum += dp[i]; } if(sum%3) return puts("-1"),0; dfs(s); if(!ans1 || !ans2) return puts("-1"),0; else cout<<ans1<<" "<<ans2<<endl; return 0; }
代码二:
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define MS(a) memset(a,0,sizeof(a)) #define MP make_pair #define PB push_back const int INF = 0x3f3f3f3f; const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } ////////////////////////////////////////////////////////////////////////// const int maxn = 1e6+10; int n; vector<int> mp[maxn]; int vis[maxn]; int val[maxn]; int v[maxn]; int avg; int ans1,ans2,s; //int tem1[maxn],tem2[maxn]; //bool flag1,flag2; int dfs1(int st){ if(vis[st] || st==ans1) return 0; vis[st]=1; val[st]=v[st]; for(int i=0; i<(int)mp[st].size(); i++){ int u = mp[st][i]; if(u == ans1) continue; val[st]+=dfs1(u); } return val[st]; } void dfs2(int st){ if(ans1 != 0) return ; for(int i=0; i<(int)mp[st].size(); i++){ dfs2(mp[st][i]); if(ans2 != 0) return ; } if(ans1==0 && val[st]==avg && st!=s) ans1 = st; } void dfs3(int st){ if(ans2 != 0) return ; for(int i=0; i<(int)mp[st].size(); i++){ if(mp[st][i]==ans1) continue; dfs3(mp[st][i]); if(ans2 != 0) return ; } if(ans2==0 && val[st]==avg && st!=s && st!=ans1) ans2 = st; } //void dfs2(int u) { // for(int i=0; i<mp[u].size(); i++) { // dfs2(mp[u][i]); // if(flag1)return ; // tem1[u]+=tem1[mp[u][i]]; // } // if(u!=s&&tem1[u]==avg) { // flag1=true; // ans1=u; // } //} // //void dfs3(int u) { // for(int i=0; i<mp[u].size(); i++) { // if(flag1&&mp[u][i]==ans1) { // continue; // } // dfs3(mp[u][i]); // if(flag2)return ; // tem2[u]+=tem2[mp[u][i]]; // } // if(u!=s&&tem2[u]==avg) { // flag2=true; // ans2=u; // } //} int main() { cin >> n; for(int x,val,i=1;i<=n;i++){ scanf("%d%d",&x,&v[i]); // tem1[i] = tem2[i] = v[i]; if(x == 0) s = i; else mp[x].push_back(i); } dfs1(s); avg=val[s]/3; if(val[s]%3){ cout << -1 << endl; return 0; } dfs2(s); if(ans1==0) return puts("-1"),0; memset(vis,0,sizeof(vis)); dfs1(s); dfs3(s); if(ans2==0) return puts("-1"),0; cout << ans1 << " " << ans2 << endl; }
Codeforces 767C. Garland (dfs)
原文:http://www.cnblogs.com/yxg123123/p/7241522.html