发布时间: 2017年3月13日 12:13 时间限制: 1000ms 内存限制: 128M
为了拯救喵哈哈村,这个世界必须要存在英雄。
一名叫做卢西奥的英雄站了出来!他现在面临一个难题:
他被要求将一棵树拆成3份,使得每一份中所有节点的权值和相等。
他希望知道,对于一棵给定的有根树,在选取其中2个非根节点并将它们与它们的父亲节点分开后,所形成的三棵子树的节点权值之和能够两两相等的方案有多少种。
两种方案被看做不同的方案,当且仅当形成方案的2个节点不完全相同。
每个输入文件包含多组输入,在输入的第一行为一个整数T,表示数据的组数。
每组输入的第一行为一个整数N,表示给出的这棵树的节点数。
接下来N行,依次描述结点1~N,其中第i行为两个整数Vi和Pi,分别描述这个节点的权值和其父亲节点的编号。
父亲节点编号为0的节点为这棵树的根节点。
满足3<=N<=100000, |Vi|<=100, T<=10
对于每组输入,输出一行Ans,表示方案的数量。
2 3 1 0 1 1 1 2 4 1 0 1 1 1 2 1 3
1 0
sum[u]:以u点为根的子树所有节点权值之和
树的总权值为sum[root],既然是平均分成三分那么每一分的值一定是sum[root]/3
总共有两种情况:
①两个切割点属于不同子树
②其中一个切割点在以另一个切割点为根的子树中
对于①:深搜时统计一下就好了
对于②:即是需要找到一个点sum[x] = sum[root]*2/3,并且在以x点为根的子树中有点满足sum[p] = sum/3,也在深
搜时统计一下就好
http://qscoj.cn/problem/43/
#include
#include
#include
using namespace std;
#define LL long long
vector G[100005];
LL ans, sum[100005], df, sa;
int root, n, val, pri[100005];
LL Jud(int u, int p)
{
int i, v;
sum[u] += pri[u];
for(i=0;i