51nod 1677 treecnt(思维)
题意:
给定一棵n个节点的树,从1到n标号。选择k个点,你需要选择一些边使得这k个点通过选择的边联通,目标是使得选择的边数最少。
现需要计算对于所有选择k个点的情况最小选择边数的总和为多少。
考虑每条边对答案的贡献,令x为这条边左边的点数,则n-x为这条边右边的点数。
满足条件的情况数=总情况数-不满足条件的情况数。即C(n,k)-(C(x,k)+C(n-x,k)).
# include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <bitset> # include <set> # include <cmath> # include <algorithm> using namespace std; # define lowbit(x) ((x)&(-x)) # define pi acos(-1.0) # define eps 1e-8 # define MOD 1000000007 # define INF 1000000000 # define mem(a,b) memset(a,b,sizeof(a)) # define FOR(i,a,n) for(int i=a; i<=n; ++i) # define FO(i,a,n) for(int i=a; i<n; ++i) # define bug puts("H"); # define lch p<<1,l,mid # define rch p<<1|1,mid+1,r # define mp make_pair # define pb push_back typedef pair<int,int> PII; typedef vector<int> VI; # pragma comment(linker, "/STACK:1024000000,1024000000") typedef long long LL; inline int Scan() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } inline void Out(int a) { if(a<0) {putchar('-'); a=-a;} if(a>=10) Out(a/10); putchar(a%10+'0'); } const int N=100005; //Code begin... struct Edge{int p, next;}edge[N<<1]; int head[N], cnt=1, siz[N]; LL fac[N], ans; int n, k; void exgcd(LL a,LL b,LL & d,LL & x,LL & y){ if(!b) d = a, x = 1, y = 0; else exgcd(b, a%b, d, y, x), y -= x*(a/b); } LL inv(LL a, LL p){ LL d, x, y; exgcd(a, p, d, x, y); return d == 1 ? (x+p)%p : -1; } void init(){ fac[k]=1; FOR(i,k+1,n) fac[i]=fac[i-1]*i%MOD*inv(i-k,MOD)%MOD; } void add_edge(int u, int v){edge[cnt].p=v; edge[cnt].next=head[u]; head[u]=cnt++;} void dfs(int x, int fa){ int tmpx, tmpy; siz[x]=1; for (int i=head[x]; i; i=edge[i].next) { int v=edge[i].p; if (v==fa) continue; dfs(v,x); siz[x]+=siz[v]; tmpx=siz[v]; tmpy=n-siz[v]; ans=(ans+fac[n]-fac[tmpx]-fac[tmpy])%MOD; } } int main () { int u, v; n=Scan(); k=Scan(); init(); FO(i,1,n) u=Scan(), v=Scan(), add_edge(u,v), add_edge(v,u); dfs(1,0); printf("%lld\n",(ans+MOD)%MOD); return 0; }