分析

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