hdu 5647 DZY Loves Connecting (树形dp)

DZY Loves Connecting

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 555    Accepted Submission(s): 195


Problem Description
DZY has an unrooted tree consisting of n nodes labeled from 1 to n .

DZY likes connected sets on the tree. A connected set S is a set of nodes, such that every two nodes u,v in S can be connected by a path on the tree, and the path should only contain nodes from S . Obviously, a set consisting of a single node is also considered a connected set.

The size of a connected set is defined by the number of nodes which it contains. DZY wants to know the sum of the sizes of all the connected sets. Can you help him count it?

The answer may be large. Please output modulo 109+7 .
 

Input
First line contains t denoting the number of testcases.
t testcases follow. In each testcase, first line contains n . In lines 2n , i th line contains pi , meaning there is an edge between node i and node pi . ( 1pii1,2in )

( n1 , sum of n in all testcases does not exceed 200000 )
 

Output
Output one line for each testcase, modulo 109+7 .
 

Sample Input
  
  
2 1 5 1 2 2 3
 

Sample Output
  
  
1 42
Hint
In the second sample, the 4 edges are (1,2),(2,3),(2,4),(3,5). All the connected sets are {1},{2},{3},{4},{5},{1,2},{2,3},{2,4},{3,5},{1,2,3},{1,2,4},{2,3,4},{2,3,5},{1,2,3,4},{1,2,3,5},{2,3,4,5},{1,2,3,4,5}. If you need a larger stack size, please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.
 

Source
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:   5674  5673  5671  5670  5669


用f[i]表示包含i的连通块数量,g[i]表示以i为根节点的连通块的数量。

下面给出DP方程:

f[n]=f[n]*(g[son[n][i]]+1)%mod+g[n]*f[son[n][i]]%mod;

f[n]%=mod;

g[n]=g[n]*(g[son[n][i]]+1)%mod;

f[n]*(g[son[n][i]]+1):对于结点包含n的连通块数量f[n],当检测到新子结点时,自身大小要乘上以子结点为根的连通块数量,同时还要加上自身

g[n]*f[son[n][i]]:子结点的连通块同样需要更新

g[n]=g[n]*(g[son[n][i]]+1):此处是对以n为根节点的连通块数量进行更新,每多一个子结点,之前的结果都要对该子树进行更新。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
const int inf = 2147483647;
const double PI = acos(-1.0);
const double e = 2.718281828459;
const int mod = 1000000007;
typedef long long LL;
#pragma comment(linker, "/STACK:102400000,102400000")
//freopen("in.txt","r",stdin); //输入重定向,输入数据将从in.txt文件中读取
//freopen("out.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中cin
const int nmax = 200005;
LL f[nmax], g[nmax];
vector<int>son[nmax];
int t;
void dp_dfs(int x, int father)
{
	for (int i = 0; i < son[x].size(); ++i)
	{
		if (son[x][i] != father)
		{
			dp_dfs(son[x][i], x);
			f[x] = (f[x] * g[son[x][i]] % mod + f[x] + g[x] * f[son[x][i]] % mod) % mod;
			g[x] = g[x] * (g[son[x][i]] + 1) % mod;
		}
	}
}
int main()
{
	int  i, j;
	int n;
	scanf("%d", &n);
	while (n--)
	{
		scanf("%d", &t);		
		fill(f, f + t + 1, 1);
		fill(g, g + t + 1, 1);
			//cout << f[1] << endl;
			for (i = 2; i <= t; ++i)
			{
				int x;
				scanf("%d", &x);
				son[x].push_back(i);
				son[i].push_back(x);
			}
			dp_dfs(1, -1);
			LL ans = 0;
			for (i = 1; i <= t; ++i)
			{
				ans += f[i];
				ans %= mod;
				son[i].clear();
			}
			cout << ans << endl;
	}
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值