分析
首先我们考虑什么时候可能有解
当整棵树的权值和为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; }