这个题没想出来,好菜QAQ...
题目要求至少经过一段黑色的边的答案,那么我们可以求总数减去不经过黑色的,这样就是答案了。
那么也就是求出每个只有红色边的连通块中有几个点。
总数就是n的k次方,设连通块有i个点,那么每次减去i的k次方就行了。
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <iomanip>
#include <string>
using namespace std;
typedef long long int ll;
ll n,k,sum;
int u,v,x;
const int maxn=100000+5;
vector<int> edge[maxn];
const int mod=1e9+7;
int vis[maxn];
ll quick_m(ll a,ll b){
ll res=1ll;
while(b){
if(b%2) res=res*a%mod;
a=a*a%mod;
b/=2;
}
return res;
}
void DFS(int x){
vis[x]=1;
sum++;
for(int i=0;i<edge[x].size();i++){
int nxt=edge[x][i];
if(!vis[nxt]) DFS(nxt);
}
}
int main(){
while(scanf("%I64d%I64d",&n,&k)!=EOF){
for(int i=0;i<=n;i++) edge[i].clear();
memset(vis,0,sizeof(vis));
for(int i=1;i<n;i++){
scanf("%d%d%d",&u,&v,&x);
if(x==0){//去掉黑色的边
edge[u].push_back(v);
edge[v].push_back(u);
}
}
ll ans=quick_m(n,k);
for(int i=1;i<=n;i++){
if(!vis[i]){
sum=0;
DFS(i);
ans=((ans-quick_m(sum,k))%mod+mod)%mod;
}
}
printf("%I64d\n",ans);
}
return 0;
}