CF 1139-C Edgy Trees(并查集)

题目: 传送门
思路: 因为选拔赛做过一道类似的题,所以直接就想到并查集了,不得不说这很巧妙。
对于题目给的每条线路,如果为 1 就不并 , 为 0 就 将二者合并 , 这样最后会的到几个集合,如果要从一个集合的某点到另一个集合的某点,则一定会经过 1 的道路。 反过来 ,集合内的点到集合内的点是不会经过含有 1 的道路的,所以我们只要用所有走法减去这样的走法就可以了。

#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;

const long long mods=1e9+7;
map<int,long long> s;
std::vector<int> v;
int f[200050];
int vis[200050];
int finds(int x) {
    return x==f[x]?x:f[x]=finds(f[x]);
}

void unions(int x,int y) {
    x= finds(x);
    y= finds(y);
    if(x==y) return ;
    else f[x] =y;
}

long long fastX(long long k,long long x) { //快速幂
    long long res = 1;
    while(k!=0) {
        if(k&1) {
            k--;
            res=res * x %mods;
        }
        k>>=1;
        x=x*x%mods;
    }
    return res;
}

int main() {
    long long n,k;
    cin>>n>>k;
    long long ans = fastX(k,n);
    for(int i=0;i<=n;i++) f[i]=i;
    for(int i=1;i<n;i++) {
        int l,r,v;
        cin>>l>>r>>v;
        if(v==1) continue;
        else unions(l,r);
    }
    for(int i=1;i<=n;i++) {
        s[finds(i)] ++;
        v.push_back(f[i]);
    }
    for(int i=0;i<v.size();i++) {
        if(vis[v[i]]==1) continue;
        ans =  (ans - fastX(k,s[v[i]])+mods)%mods;
        vis[v[i]] = 1;
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43305984/article/details/89205672