喵哈哈村的卢西奥
为了拯救喵哈哈村,这个世界必须要存在英雄。
一名叫做卢西奥的英雄站了出来!他现在面临一个难题:
他被要求将一棵树拆成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
题解
两种情况:
第一种情况,有两个是子树,这个东西用启发式合并/dp去维护一下当前sz[x]=all/3的个数就好了。
第二种情况,只有一个是子树,那么第二段显然是包含了第一段的,那么就存在一个的size=2all/3,一个sz=all/3的情况,统计一下就好了。
dfs处理一下就好了,具体看代码:
#include<bits/stdc++.h>
// #include <unordered_set>
using namespace std;
#define FF first
#define SS second
#define MP make_pair
#define PB push_back
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define FOR(i, n, m) for(int i = n; i <= m; i++)
#define REP(i, n, m) for(int i = n; i >= m; i--)
#define ll long long
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL, LL> PLL;
typedef unsigned long long ULL;
/****************************define***************************************/
const int mod = 1e9 + 7;
const int maxn = 100010;
int n;
int v[maxn], sz[maxn], p[maxn];
vector<int> nd[maxn];
int s;
int cn = 0, cn2 = 0;
ll ans = 0;
void Dfs_sz(int u){
sz[u] += v[u];
int t = nd[u].size();
FOR(i, 0, t-1) {
Dfs_sz(nd[u][i]);
sz[u] += sz[nd[u][i]];
}
}
void Dfs(int u){
//printf("node %d. ans %d. cn %d. cn2 %d. sz %d\n", u, ans, cn, cn2, sz[u]);
if(sz[u] == s/3) {
ans += cn + cn2;
//printf("node %d. ans %d\n", u, ans);
}
if(p[u] != 0 && sz[u] == s*2/3) cn2++;
int t = nd[u].size();
FOR(i, 0, t-1){
Dfs(nd[u][i]);
}
if(sz[u] == s/3) cn++;
if(p[u] != 0 && sz[u] == s*2/3) cn2--;
}
int main(){
int t;
cin >> t;
while(t--){
cn = 0, cn2 = 0;
s = 0, ans = 0;
FOR(i, 0, maxn-1) nd[i].clear();
memset(sz, 0, sizeof(sz));
int n, root=-1;
cin >> n;
FOR(i, 1, n) {
cin >> v[i] >> p[i];
s += v[i];
nd[p[i]].PB(i);
if(p[i] == 0) root=i;
}
if(s % 3 != 0) cout << 0 << endl;
else{
Dfs_sz(root);
Dfs(root);
printf("%lld\n", ans);
}
}
return 0;
}