分析
首先我们考虑什么时候可能有解
当整棵树的权值和为3的倍数时(显然
至于判断是否可以分成这三个等分时
我们先考虑两次分割深度最大的那一次
分出来等于答案的一定是它的子树
且我们知道,当一个子树权值和时
我们必须要把它分出去
否则它不可能存在于其他任何分区
所以我们每次遇到子树权值和等于的
直接减去即可
代码
//CF767C
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define LL long long
#define Cl(X,Y) memset((X),(Y),sizeof(X))
#define FOR(i,A,B) for(int i=A;i<=B;i++)
#define BOR(i,A,B) for(int i=A;i>=B;i--)
#define Lowbit(X) (X & (-X))
#define Skip cout<<endl;
#define INF 0x3f3f3f3f
#define Mod 998244353
#define Rson (X<<1|1)
#define Lson (X<<1)
using namespace std;
const int MaxN=1e6+10;
int Next[MaxN<<1],Head[MaxN],End[MaxN<<1],Cur;
int Num[MaxN],Total,Size[MaxN],Root;
int u,v,w,Tot;
pair<int,int>Ans;
inline void File() {
freopen(".in","r",stdin);
freopen(".out","w",stdout);
}
inline void Add_Edge(int From,int To) {
Next[++Cur]=Head[From];
Head[From]=Cur;
End[Cur]=To;
}
inline void Search(int New,int Pre) {
Size[New]=Num[New];
for(int i=Head[New];i;i=Next[i]) {
if(End[i]==Pre) continue;
Search(End[i],New);
Size[New]+=Size[End[i]];
}
if(Size[New]==Tot) { Ans.first ? (Ans.second ? Ans=Ans : Ans=make_pair(Ans.first,New)) : Ans=make_pair(New,0); Size[New]-=Tot; }
}
int main() {
// File();
ios::sync_with_stdio(false);
cin>>Total;
FOR(i,1,Total) {
cin>>u>>Num[i];
Tot+=Num[i];
if(u==0) { Root=i; continue; }
Add_Edge(u,i);
}
if(Tot%3) { cout<<"-1"<<endl; return 0; }
Tot/=3;
Ans=make_pair(0,0);
Search(Root,0);
// FOR(i,1,Total) { cout<<"i: "<<i<<" Size: "<<Size[i]<<endl; }
if(!Ans.second || Ans.first==Root || Ans.second==Root) { cout<<"-1"<<endl; }
else { cout<<Ans.first<<" "<<Ans.second<<endl; }
system("pause");
return 0;
} 
京公网安备 11010502036488号