'
1 对树后序遍历一遍,s【i】里存的是结点i上所有子树结点权值和(包括这个结点,但不包括那些已经切去的结点)
从叶子往上遍历,当s【i】等于sum/3时,就在这个点切,当切去两个部分之后就不切了,最后看看剩下的部分等不等于sum/3就行了
上代码了 QAQ
#include <algorithm> #include <stack> #include <istream> #include <stdio.h> #include <map> #include <math.h> #include <vector> #include <iostream> #include <queue> #include <string.h> #include <set> #include <cstdio> #define FR(i,n) for(int i=0;i<n;i++) #define MAX 2005 #define mkp pair <int,int> using namespace std; const int maxn = 2e6+3; typedef long long ll; void read(int &x) { char ch; bool flag = 0; for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar()); for (x = 0; isdigit(ch); x = (x << 1) + (x << 3) + ch - 48, ch = getchar()); x *= 1 - 2 * flag; } int n,sum=0,total[maxn]; int top=0; vector <int> v1[maxn]; int val[maxn]; int start=-1; int ans[5]; void dfs(int cnt,int last) { int k=v1[cnt].size(); // printf("%d\n",k); for(int i=0;i<k;i++) { if(v1[cnt][i]!=last) { dfs(v1[cnt][i],cnt); val[cnt]+=val[v1[cnt][i]]; } } if(val[cnt]==sum&&top<2&&cnt!=start) { val[cnt]=0; ans[top++]=cnt; } } int main() { scanf("%d",&n); memset(total,0,sizeof(total)); for(int i=1;i<=n;i++){ int l,r; scanf("%d",&l); if(!l)start=i; else v1[l].push_back(i); scanf("%d",&r);val[i]=r; sum+=r; } if(sum%3){puts("-1");return 0;} int tmp=sum; sum/=3; dfs(start,-1); // for(int i=1;i<=n;i++)printf("%d ",val[i]); // printf("%d\n",top); if(top==2&&val[start]==sum) { printf("%d %d\n",ans[0],ans[1]); } else puts("-1"); return 0; }