Codeforces-Round#548(Div.2)-C-Edgy Trees-快速幂

这个题没想出来,好菜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;
}

  

猜你喜欢

转载自www.cnblogs.com/JustDoA/p/10586090.html