#1479 : 三等分(树形DP)
http://hihocoder.com/problemset/problem/1479
#1479 : 三等分
描述
小Hi最近参加了一场比赛,这场比赛中小Hi被要求将一棵树拆成3份,使得每一份中所有节点的权值和相等。
比赛结束后,小Hi发现虽然大家得到的树几乎一模一样,但是每个人的方法都有所不同。于是小Hi希望知道,对于一棵给定的有根树,在选取其中2个非根节点并将它们与它们的父亲节点分开后,所形成的三棵子树的节点权值之和能够两两相等的方案有多少种。
两种方案被看做不同的方案,当且仅当形成方案的2个节点不完全相同。
输入
每个输入文件包含多组输入,在输入的第一行为一个整数T,表示数据的组数。
每组输入的第一行为一个整数N,表示给出的这棵树的节点数。
接下来N行,依次描述结点1~N,其中第i行为两个整数Vi和Pi,分别描述这个节点的权值和其父亲节点的编号。
父亲节点编号为0的节点为这棵树的根节点。
对于30%的数据,满足3<=N<=100
对于100%的数据,满足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
参考博客:http://blog.csdn.net/viphong/article/details/61958631
需要两个dfs,第一个dfs从父节点开始递归遍历,求出以每个节点为根的子树的权值和。
第二个dfs就是开始统计个数: 若某一节点正好是总数的1/3,那么该节点很有可能和另一个节点符合题目要求,那么另一个节点就是另一个1/3节点,或者另一个节点是该节点祖先节点,这个祖先节点是总数的2/3#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int Max = + ;
int v[Max], sum[Max];
long long all, first, second, cnt, root;
vector<int> mp[Max];
//统计每个子树的权值和
void dfs(int node, int fa)
{
sum[node] = v[node];
for (int i = ; i < (int)mp[node].size(); i++)
{
int son = mp[node][i];
if (son != fa)
{
dfs(son, node);
sum[node] += sum[son];
}
}
}
// 核心
void dfs2(int node, int fa)
{
//找到一个1/3节点
if (sum[node] == all)
cnt += first + second;
// 因为可能有负数,所有要继续往下递归
if (sum[node] == all * && node != root)
second++; for (int i = ; i < (int)mp[node].size(); i++)
{
int son = mp[node][i];
if (son != fa)
{
dfs2(son, node);
}
}
//每一个1/3的节点只会和另一个不同分支的1/3节点满足条件
//每一个1/3的节点只会和它祖先是2/3的满足条件
if (sum[node] == all)
first++;
//以node为根节点满足2/3,全都遍历完毕,所以再不存在以node为根与一个1/3节点满足条件,故删除该2/3节点
if (sum[node] == all * && node != root)
second--;
}
int main()
{
int n, t, fa;
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
//清空
for (int i = ; i <= n; i++)
mp[i].clear();
memset(sum, , sizeof(sum));
cnt = all = first = second = ;
for (int i = ; i <= n; i++)
{
scanf("%d%d", &v[i], &fa);
all += v[i];
if (fa == )
root = i;
mp[fa].push_back(i);
}
if (all % )
{
printf("0\n");
continue;
}
all /= ;
dfs(root, );
dfs2(root, );
printf("%lld\n", cnt);
}
return ;
}
#1479 : 三等分(树形DP)的更多相关文章
- Hihocoder #1479 : 三等分 树形DP
三等分 描述 小Hi最近参加了一场比赛,这场比赛中小Hi被要求将一棵树拆成3份,使得每一份中所有节点的权值和相等. 比赛结束后,小Hi发现虽然大家得到的树几乎一模一样,但是每个人的方法都有所不同.于 ...
- SPOJ 1479 +SPOJ 666 无向树最小点覆盖 ,第二题要方案数,树形dp
题意:求一颗无向树的最小点覆盖. 本来一看是最小点覆盖,直接一下敲了二分图求最小割,TLE. 树形DP,叫的这么玄乎,本来是线性DP是线上往前\后推,而树形DP就是在树上,由叶子结点状态向根状态推. ...
- poj3417 LCA + 树形dp
Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4478 Accepted: 1292 Descripti ...
- COGS 2532. [HZOI 2016]树之美 树形dp
可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...
- 【BZOJ-4726】Sabota? 树形DP
4726: [POI2017]Sabota? Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 128 Solved ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- 树形DP
切题ing!!!!! HDU 2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...
- BZOJ 2286 消耗战 (虚树+树形DP)
给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...
- POJ2342 树形dp
原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...
随机推荐
- 前端base64、baseurl加解密和RSA加解密
由于项目最近要进行安全测试,前端的用户和密码都是明文数据传送给后台那里,其实这样很很不安全的,容易泄露个人信息和密码.中间服务器的同事就提出,可以通过前端接收公钥,利用公钥对密码进行加密,把加密过密码 ...
- POJ 1017 最少包裹
参考自:https://www.cnblogs.com/ECJTUACM-873284962/p/6414760.html Packets Time Limit: 1000MS Memory Li ...
- Android 根据版本号更新
1 读取android 版本号 具体文件位置: app下 build.gradle文件 versionCode和 versionName defaultConfig { versionCode 1 v ...
- CH0805 防线(算竞进阶习题)
二分 一道藏的很深的二分题... 题目保证只有一个点有奇数个防具,这个是突破口. 因为 奇数+偶数=偶数,我们假设某个点x,如果有奇数点的防具在x的左边,那么x的左边的防具总数一定是奇数,右边就是偶数 ...
- Hard Life UVA - 1389(最大密度子图 输出点集)
题意: rt 解析: 我用的第二种方法... s向所有的边连权值为1的边 所有的点向t连权值为mid的边 如果存在u - > v 则边向u和v分别连一条权值为INF的边 二分mid 用dfs ...
- 使用tree命令导出文件夹/文件的目录树
前提:己安装扩展: 介绍: TREE [drive:][path] [/F] [/A] /F 显示每个文件夹中文件的名称.(带扩展名) /A 使用 ASCII 字符,而不使用扩展字符. t ...
- SpringMVC 拦截器使用说明
spring-content.xml <!-- 配置用于session验证的拦截器 --> <!-- 如果有多个拦截器满足拦截处理的要求,则依据配置的先后顺序来执行 --> & ...
- Android sqlitedatabase 事务
SQLiteDatabase的beginTransaction()方法可以开启一个事务,程序执行到endTransaction() 方法时会检查事务的标志是否为成功,如果为成功则提交事务,否则回滚事务 ...
- 超详解的LNMP搭建并优化
环境为Centos7 nginx1.14 mysql5.7 php7一,安装Nginx (yum装,快速) yum install nginx二,优化nginx (方便后期工作,如果纯为测试的话,不用 ...
- NOIP2018凉凉记
首先声明一下,我去不了TG,因为我太菜了GD的某教授把我打到PJ了…… 虽然就我这实力普及都不一定1= 不管了,这次是普及,就当扎实基础了.反正HF的 $\text{hhz}$ 也考PJ,见个面多好啊 ...