看似很难,实则很简单的一道题,把样例推出来就想明白了。
首先从正面肯定不好搞,故反面求之,若一条边的color是0,可知k位可以从该边连接的两点任选,,减去2^ k。同理,若由三个点两两相连的边都是0,那么从3个点人选,即3^k。
想到了什么??
对,就是并查集!
最后,对一个点,若与之相连的所有边都是1,就要减1,也就是1^k。
#include<bits/stdc++.h>
using namespace std;
#define forn(i,n) for(int i = 0;i<int(n);i++)
typedef long long LL;
const LL mod = 1e9 + 7;
LL n,k,ans,u,v,w,cnt;
int fa[202020],num[202020];
bool is[202020];
LL fastmuti(LL a,LL b){
LL ans = 0;
while(b){
if(b & 1) ans = (ans + a) % mod;
a = (a + a) % mod;
b >>=1 ;
}
return ans;
}
LL fastmi(LL a,LL n){
LL ans = 1;
while(n){
if(n&1) ans = fastmuti(ans,a);
a = fastmuti(a,a);
n>>=1;
}
return ans;
}
int find(int x){
return x ==fa[x] ? x : fa[x] = find(fa[x]);
}
void Union(int u,int v){
u = find(u);v = find(v);
fa[u] = v;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
//cout<<fastmi(1,5)<<endl;
cin>>n>>k;
for(int i = 1;i<=n;i++) fa[i] = i;
for(int i = 1;i<n;i++){
cin>>u>>v>>w;
if(!w) {
is[u] = is[v] =1 ;
Union(u,v);
}
}
for(int i = 1;i<=n;i++)
if(is[i]) cnt++;
ans = fastmi(n,k);
for(int i = 1;i<=n;i++)
num[find(i)]++;
for(int i = 1;i<=n;i++){
if(num[i]) ans -= fastmi(num[i],k);
ans = (ans + mod ) %mod;
}
cout<<(ans + mod) % mod;
return 0;
}