Happy Path

博客内容介绍了如何计算树中每个节点的子节点数量,然后将这些数量相加得到总数。通过模拟代码展示了如何使用动态规划(dp)来实现这一过程,并给出了具体的计算示例,最终得出结果为10。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Sample Input 1 

1
3 2
1 2
3 2

Sample Output 1

2

解析:其实我们只需要求得每个节点的“儿子”有多少个,然后把它们相加即可,结果是:0+1+2+0+4+3=10;

例如:

以下过程按代码进行模拟:

son [ 6 ] = 0;                               dp[ 6 ] = 0;                                                                                 son [ 6 ]=1;//叶节点设为0

son [ 5 ] += son [ 6 ] =1;             dp[ 5 ] += dp [ 6 ] =0;          dp[ 5 ] += son [ 5 ] =0+1=1;            son [ 5 ]++;

son [ 2 ] += son [ 5 ] =2;             dp[ 2 ] += dp [ 5 ] =1;          dp[ 2 ] += son [ 2] =1+2=3;             son [ 2 ]++;

son [ 4 ] = 0;                                                                                                                                  son [ 4 ] =1;//叶节点设为0

son [ 1 ] += son [ 2 ] =3;             dp[ 1 ] +=dp[ 2 ] =3;                                                                                   

              += son [ 4 ] =4;             dp[ 1 ] +=dp[ 4 ]=3;              dp[ 1 ] += son [ 1 ] =3+4=7;           son [ 1 ]++;

son [ 3 ] += son [ 2 ] =2;              dp[ 3 ]+=son[ 2 ]=3;

相加的过程是通过dp[ ] 实现的,ans只需要找到入度为0的点,把该点的 dp[ ] 值加上即可;

ans += dp [ 1 ] =7;

ans += dp [ 3 ] =7+3=10;

即结果为:10;

详细看代码;

#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
#include <cstring>
#include<iostream>
using namespace std;
const int MAXN = 100010;
const int mod = 1e9 + 7;
vector<int> G[MAXN];
int vis[MAXN], in[MAXN];
int son[MAXN], dp[MAXN];
long long ans;

void dfs(int x) {
	if(!G[x].size()) {//如果执行这一步,说明x为叶节点 
		son[x] = 1;
		return ;
	}
	for(int i = 0; i < G[x].size(); ++i) {
		int u = G[x][i];
		if(vis[u]) {
			son[x] += son[u];
			son[x] %= mod;
			continue;
		}
		vis[u] = 1;
		dfs(u);
		dp[x] += dp[u];//路径数 
		son[x] += son[u];
		dp[x] %= mod, son[x] %= mod;
	}
	
	dp[x] += son[x];
	son[x]++;//把自己加上 
	dp[x] %= mod, son[x] %= mod;
}

int main() {
	int n, m, T;
	scanf("%d", &T);
	while(T--) {
		for(int i = 0; i < MAXN; ++i) G[i].clear(), son[i] = 0;
		for(int i = 0; i < MAXN; ++i) vis[i] = in[i] = dp[i] = 0;
		scanf("%d %d", &n, &m);
		for(int i = 0; i < m; ++i) {
			int a, b;
			scanf("%d %d", &a, &b);
			in[b]++;
			G[a].push_back(b);
		}
		for(int i = 1; i <= n; ++i) {
            sort(G[i].begin(), G[i].end());//从小到大排序 
            G[i].erase(unique(G[i].begin(), G[i].end()), G[i].end());
        }//删除重边,题目要求点不一样,留一条边即可 
		ans = 0;
		for(int i = 1; i <= n; ++i) {
			if(in[i]) continue;//找入度为0的点,入度不是0,则continue 
			dfs(i);
			ans += dp[i];
			ans %= mod;
		}
		printf("%lld\n", ans);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值