题意:
给定n个点的树,求选出一个联通子图的方案数,答案对1e9+7取模。
数据范围:n<=2e5
解法:
设 d [ x ] 以 x 为 根 的 子 树 中 , 选 择 点 x 之 后 , 连 通 子 图 的 方 案 数 , 设 v 是 x 的 子 节 点 , 那 么 转 移 方 程 为 : 1. 如 果 选 择 点 v , 那 么 方 案 数 为 d [ x ] ∗ d [ v ] . 2. 如 果 不 选 择 点 v , 那 么 d [ x ] . 综 上 得 转 移 方 程 为 : d [ x ] = d [ x ] ∗ ( d [ v ] + 1 ) . 设d[x]以x为根的子树中,选择点x之后,连通子图的方案数,\\ 设v是x的子节点,那么转移方程为:\\ 1.如果选择点v,那么方案数为d[x]*d[v].\\ 2.如果不选择点v,那么d[x].\\ 综上得转移方程为:d[x]=d[x]*(d[v]+1). 设d[x]以x为根的子树中,选择点x之后,连通子图的方案数,设v是x的子节点,那么转移方程为:1.如果选择点v,那么方案数为d[x]∗d[v].2.如果不选择点v,那么d[x].综上得转移方程为:d[x]=d[x]∗(d[v]+1).
code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxm=2e6+5;
const int mod=1e7+7;
vector<int>g[maxm];
int d[maxm];
int n;
int ans;
void dfs(int x,int fa){
d[x]=1;
for(int v:g[x]){
if(v==fa)continue;
dfs(v,x);
d[x]=d[x]*(d[v]+1)%mod;
}
ans=(ans+d[x])%mod;
}
signed main(){
ios::sync_with_stdio(0);
cin>>n;
for(int i=1;i<n;i++){
int a,b;cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1,1);
cout<<ans<<endl;
return 0;
}