题目链接:http://codeforces.com/problemset/problem/1139/C
题目大意:给了一棵树,n个点,m条边。让从中选k个点,使得从a1到a2,a2到a3,ak-1到ak的路径中至少经过一条黑色的边,问这样的集合有多少个。
思路:并查集求红色边的所用联通块,然后用总的情况减去联通块的集合(用快速幂求)。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+1000;
typedef long long ll;
const ll mod=1e9+7;
ll n,k;
ll fa[maxn],ma[maxn];
ll pow(ll a,ll b)
{
ll res=1;
a=a%mod;
while(b)
{
if(b&1)
res=res*a%mod;
a=a*a%mod;
b/=2;
}
return res%mod;
}
void iint()
{
for(ll i=1;i<=maxn;i++)
{
fa[i]=i;
ma[i]=1;
}
}
ll findd(ll x)
{
if(x!=fa[x])
{
return fa[x]=findd(fa[x]);
}
return fa[x];
}
int main()
{
iint();
scanf("%lld%lld",&n,&k);
for(ll i=1;i<=n-1;i++)
{
ll a,b,c;
cin>>a>>b>>c;
if(c==0)
{
ll x=findd(a);
ll y=findd(b);
fa[x]=y;
ma[y]=ma[y]+ma[x];
}
}
ll ans1=pow(n,k);
ll ans=0;
for(ll i=1;i<=n;i++)
{
if(findd(i)==i)
{
ans=(ans%mod+pow(ma[i],k))%mod;
}
}
cout<<(ans1-ans+mod)%mod<<endl;
}