传送门:点击打开链接
题意:一棵树,每个节点有一个权值t,把它分成三部分,每部分要求权值和相等。
分析:先可以先算出总大小sum。接着%3看能不能分,不能-1,能继续。然后递归算出每个子树的权值和。直接dfs,回溯的时候如果满足条件就清0并记录下来。注意由与权值可能有正有负,所以可能不止三部分满足条件,但是只要输出先找到的地方就行。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define eps 1e-10
const int N = 1e6+5;
vector<int> e[N];
int w[N],ct[2],sum,id,n,rt;
void dfs(int x) {
for(int i=0;i<e[x].size();i++) {
int u = e[x][i];
dfs(u);
w[x]+=w[u];
}
if(w[x]==sum/3&&x!=rt) {
if(id>1) return ;
w[x]=0;
ct[id++]=x;
}
}
//输入挂
inline int getint(){//inline是为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题
int x=0,f=1;
char c=getchar();
while(c>'9'||c<'0'){
if(c == '-')
f = -1;
c = getchar();
}
while(c>='0' && c<='9'){
x = x*10+c-48;
c=getchar();
}
return x*f;
}
int main() {
ios::sync_with_stdio(0);
///scanf("%d",&n);
n=getint();
for(int i=1;i<=n;i++) {
int u,v;
///cin>>u>>w[i];
///scanf("%d%d",&u,&w[i]);
u=getint(),w[i]=getint();
sum += w[i];
if(u) e[u].pb(i);
else rt=i;
}
if(sum%3) printf("-1\n");
else {
dfs(rt);
if(id==2) printf("%d %d\n",ct[0],ct[1]);
else printf("-1\n");
}
}