容斥
按照套路,按边考虑。一条边能贡献的答案是选的k个点分居两侧的方案数。发现这东西很难求。于是转成容斥求k个点归于一侧的方案数。
#include<cstdio>
#define N 100005
#define MOD 1000000007
using namespace std;
namespace runzhe2000
{
typedef long long ll;
int fac[N], inv[N], inc[N], last[N], ecnt, ans, tot, n, k;
struct edge{int next, to;}e[N<<1];
void addedge(int a, int b)
{
e[++ecnt] = (edge){last[a], b};
last[a] = ecnt;
}
int C(int x, int y)
{
if(x < y) return 0;
return (ll) fac[x] * inc[y] % MOD * inc[x-y] % MOD;
}
int dfs(int x, int f)
{
int siz = 1;
for(int i = last[x]; i; i = e[i].next)
{
int y = e[i].to;
if(y == f) continue;
siz += dfs(y, x);
}
(ans += ((tot - C(siz, k)) % MOD - C(n-siz, k)) % MOD) %= MOD;
return siz;
}
void main()
{
scanf("%d%d",&n,&k);
for(int i = 1; i < n; i++)
{
int x, y; scanf("%d%d",&x,&y);
addedge(x,y); addedge(y,x);
}
fac[0] = fac[1] = inv[1] = inc[0] = inc[1] = 1;
for(int i = 2; i <= n; i++)
{
fac[i] = (ll)fac[i-1]*i%MOD;
inv[i] = (ll)(MOD-MOD/i)*inv[MOD%i]%MOD;
inc[i] = (ll)inc[i-1]*inv[i]%MOD;
}
tot = C(n,k);
dfs(1,0);
printf("%d\n",(ans+MOD)%MOD);
}
}
int main()
{
runzhe2000::main();
}