有2种情况。都选tot/3的节点,那么,各节点记录子节点的为tot/3的乘一下。然后是祖先是tot/3*2的乘以子树中tot/3的数量。
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <iomanip> #include <cstring> #include <map> #include <queue> #include <set> #include <cassert> #include <stack> #include <bitset> #include <list> #define mkp make_pair #define err cout<<"err"<<endl using namespace std; const double EPS=1e-12; typedef long long lon; typedef unsigned long long ull; const lon SZ=100010,SSZ=2*SZ,APB=52,one=1; const lon INF=0x7f7f7f7f,mod=1000000007; int n,arr[SZ],sum[SZ],num[SZ],tot; vector<int> mp[SZ]; lon ans; void dfs1(int x,int p) { sum[x]=arr[x]; //cout<<"x: "<<x<<" "<<arr[x]<<endl; for(int i=0;i<mp[x].size();++i) { int to=mp[x][i]; if(to!=p) { dfs1(to,x); sum[x]+=sum[to]; } } } void dfs2(int x,int p) { if(sum[x]==tot/3)++num[x]; //cout<<"x: "<<x<<" "<<sum[x]<<" "<<num[x]<<endl; lon pre=0; lon tmp=(sum[x]==tot/3*2)&&(p!=-1); for(int i=0;i<mp[x].size();++i) { int to=mp[x][i]; if(to!=p) { dfs2(to,x); num[x]+=num[to]; ans+=pre*num[to]; ans+=tmp*num[to]; pre+=num[to]; } } } void init() { cin>>n; for(int i=1;i<=n;++i) { int a,b; cin>>a>>b; arr[i]=a; if(!b)continue; mp[i].push_back(b); mp[b].push_back(i); } dfs1(1,-1); tot=sum[1]; if(tot%3) { cout<<0<<endl; } else { dfs2(1,-1); cout<<ans<<endl; } } void work() { } void release() { for(int i=1;i<=n;++i) { mp[i].clear(); num[i]=0; } ans=0,tot=0; } int main() { std::ios::sync_with_stdio(0); //freopen("d:\\1.txt","r",stdin); int casenum; cin>>casenum; //cout<<casenum<<endl; for(int time=1;time<=casenum;++time) //for(int tim=1;cin>>n;++tim) { init(); work(); release(); } return 0; }