基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
给定一棵n个节点的树,从1到n标号。选择k个点,你需要选择一些边使得这k个点通过选择的边联通,目标是使得选择的边数最少。
现需要计算对于所有选择k个点的情况最小选择边数的总和为多少。
样例解释:
一共有三种可能:(下列配图蓝色点表示选择的点,红色边表示最优方案中的边)
选择点{1,2}:至少要选择第一条边使得1和2联通。
选择点{1,3}:至少要选择第二条边使得1和3联通。
选择点{2,3}:两条边都要选择才能使2和3联通。
Input
第一行两个数n,k(1<=k<=n<=100000) 接下来n-1行,每行两个数x,y描述一条边(1<=x,y<=n)
Output
一个数,答案对1,000,000,007取模。
Input示例
3 2
1 2
1 3
Output示例
4
//考虑边的贡献即可,因为,要选k个点,这条边连接的两个连通块大小为x,y的话,贡献为C(n,k)-C(x,k)-C(y,k)
1 # include <cstdio> 2 # include <cstring> 3 # include <cstdlib> 4 # include <iostream> 5 # include <vector> 6 # include <queue> 7 # include <stack> 8 # include <map> 9 # include <bitset> 10 # include <sstream> 11 # include <set> 12 # include <cmath> 13 # include <algorithm> 14 # pragma comment(linker,"/STACK:102400000,102400000") 15 using namespace std; 16 # define LL long long 17 # define pr pair 18 # define mkp make_pair 19 # define lowbit(x) ((x)&(-x)) 20 # define PI acos(-1.0) 21 # define INF 0x3f3f3f3f3f3f3f3f 22 # define eps 1e-8 23 # define MOD 1000000007 24 25 inline int scan() { 26 int x=0,f=1; char ch=getchar(); 27 while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();} 28 while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} 29 return x*f; 30 } 31 inline void Out(int a) { 32 if(a<0) {putchar('-'); a=-a;} 33 if(a>=10) Out(a/10); 34 putchar(a%10+'0'); 35 } 36 # define MX 100005 37 /**************************/ 38 39 int n,k; 40 LL ans; 41 vector<int> G[MX]; 42 int son[MX]; 43 LL cbk[MX]; 44 45 LL qk_mi(LL a,LL b) 46 { 47 LL res = 1; 48 while(b) 49 { 50 if (b&1) res=res*a%MOD; 51 b/=2; 52 a=a*a%MOD; 53 } 54 return res; 55 } 56 57 void dfs(int x,int pre) 58 { 59 son[x]=1; 60 for (int i=0;i<G[x].size();i++) 61 { 62 if (G[x][i]==pre) continue; 63 dfs(G[x][i],x); 64 son[x]+=son[ G[x][i] ]; 65 } 66 ans = (ans+cbk[n]-cbk[son[x]]-cbk[n-son[x]]+2*MOD)%MOD; 67 } 68 69 int main() 70 { 71 scanf("%d%d",&n,&k); 72 for (int i=1;i<=n-1;i++) 73 { 74 int a,b; 75 scanf("%d%d",&a,&b); 76 G[a].push_back(b); 77 G[b].push_back(a); 78 } 79 80 cbk[k]=1; 81 for (int i=k+1;i<=n;i++) 82 { 83 LL inv=qk_mi(i-k,MOD-2); 84 cbk[i]=((cbk[i-1]*i)%MOD*inv)%MOD; 85 } 86 87 88 ans = 0; 89 dfs(1,-1); 90 printf("%lld ",ans); 91 return 0; 92 }