Description
外星人又双叒叕要攻打地球了,外星母舰已经向地球航行!这一次,JYY已经联系好了黄金舰队,打算联合所有JSO
Ier抵御外星人的进攻。在黄金舰队就位之前,JYY打算事先了解外星人的进攻计划。现在,携带了监听设备的特工
已经秘密潜入了外星人的母舰,准备对外星人的通信实施监听。外星人的母舰可以看成是一棵n个节点、n-1条边的
无向树,树上的节点用1,2…n编号。JYY的特工已经装备了隐形模块,可以在外星人母舰中不受限制地活动,可以
神不知鬼不觉地在节点上安装监听设备。如果在节点u安装监听设备,则JYY能够监听与u直接相邻所有的节点的通
信。换言之,如果在节点u安装监听设备,则对于树中每一条边(u,v),节点v都会被监听。特别注意放置在节点u的
监听设备并不监听u本身的通信,这是JYY特别为了防止外星人察觉部署的战术。
JYY的特工一共携带了k个监听设备,现在JYY想知道,有多少种不同的放置监听设备的方法,能够使得母舰上所有
节点的通信都被监听?为了避免浪费,每个节点至多只能安装一个监听设备,且监听设备必须被用完。
Input
输入第一行包含两个整数n,k,表示母舰节点的数量n和监听设备的数量k。
接下来n-1行,每行两个整数u,v(1≤u,v≤n),表示树中的一条边。
1≤n≤10^5,1≤k≤min{n,100}
Output
输出一行,表示满足条件的方案数。
因为答案可能很大,你只需要输出答案mod 1,000,000,007的余数即可
Sample Input
5 3
1 2
2 3
3 4
4 5
Sample Output
1
样例解释
样例数据是一条链
1–2–3–4–5
首先,节点 2和 4必须放置监听设备,否则 1,5将无法被监听(放置的监听设备无法监听它所在的节点)。剩下一
个设备必须放置在 3号节点以同时监听 2,4因此在 2,3,4节点放置监听设备是唯一合法的方案。
解题思路:
注意答案是恰好安k个的方案数。
设
f[i][j][0/1][0/1]
f
[
i
]
[
j
]
[
0
/
1
]
[
0
/
1
]
表示
i
i
的子树内安了 个监听器,
i
i
<script type="math/tex" id="MathJax-Element-5">i</script> 处是否安了监听器,是否被监听,直接dp即可。
#include<bits/stdc++.h>
#define ll unsigned long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
if(c=='-')c=getchar(),f=-1;
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=100005,mod=1e9+7;
int n,K,f[N][105][2][2],size[N];ll tmp[105][2][2];
int tot,first[N],nxt[N<<1],to[N<<1];
inline void add(int &x,ll y)
{
x=(x+y>=mod?x+y-mod:x+y);
}
void Add(int x,int y)
{
nxt[++tot]=first[x],first[x]=tot,to[tot]=y;
}
void dfs(int u,int fa)
{
size[u]=1;f[u][0][0][0]=f[u][1][1][0]=1;
for(int e=first[u];e;e=nxt[e])
{
int v=to[e];if(v==fa)continue;
dfs(v,u);
for(int i=0,r=min(size[u],K);i<=r;i++)
for(int j=0;j<=1;j++)
for(int k=0;k<=1;k++)
tmp[i][j][k]=f[u][i][j][k],f[u][i][j][k]=0;
for(int i=0,r1=min(size[u],K);i<=r1;i++)
for(int j=0,r2=min(size[v],K);i+j<=K&&j<=r2;j++)
{
add(f[u][i+j][0][0],tmp[i][0][0]*f[v][j][0][1]%mod);
add(f[u][i+j][0][1],(tmp[i][0][0]*f[v][j][1][1]+tmp[i][0][1]*(f[v][j][0][1]+f[v][j][1][1]))%mod);
add(f[u][i+j][1][0],tmp[i][1][0]*(f[v][j][0][0]+f[v][j][0][1])%mod);
add(f[u][i+j][1][1],(tmp[i][1][0]*(f[v][j][1][0]+f[v][j][1][1])+tmp[i][1][1]*(f[v][j][0][0]+f[v][j][1][0])+tmp[i][1][1]*(f[v][j][0][1]+f[v][j][1][1]))%mod);
}
size[u]+=size[v];
}
}
int main()
{
//freopen("action.in","r",stdin);
//freopen("action.out","w",stdout);
n=getint(),K=getint();
for(int i=1;i<n;i++)
{
int x=getint(),y=getint();
Add(x,y),Add(y,x);
}
dfs(1,0);
cout<<(f[1][K][0][1]+f[1][K][1][1])%mod<<'\n';
return 0;
}