Loading

【题解】【CF】CF1108F MST Unification

 

 

CF1108F MST Unification

CF1108F MST Unification

1 题外话

在这道题之前应该还有个题要写,但是实(ma)在(liang)太(tai)难(da)就不写了(

2 sol

首先通过考虑kruskal的过程思考为什么会有不同的MST存在

设当前要连接的边为\((u,v)\) ,如果在连接这两条边之后有一个边\((x,y)\) ,与\((u,v)\) 冲突,而且权值相等,那么此时就可以二选一,MST就多了一种可能

容易发现,这是唯一一种可以让多种MST存在的可能

只需要考虑把所有的多出来的边权值+1即可排除这种可能

3 code

码量极小,是绝世好题(

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=200010;

inline void read(int &x) {
    x=0;
    int f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {
        if (ch=='-') {
            f=-1;
        }
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    x*=f;
}

struct edge {
    int x,y;
    int val;
};

int n,m;
edge e[N<<1];
int ans;

inline bool comp(const edge &x,const edge &y) {
    return x.val<y.val;
}

int fa[N];

inline int find(int x) {
    return fa[x]==x?x:fa[x]=find(fa[x]);
}

inline int check(int x,int y) {
    return find(x)==find(y);
}

inline void merge(int x,int y) {
    fa[find(x)]=find(y);
}

int main() {
    read(n),read(m);
    for(int i=1;i<=n;i++) {
        fa[i]=i;
    }
    for(int i=1;i<=m;i++) {
        read(e[i].x),read(e[i].y),read(e[i].val);
    }
    sort(e+1,e+1+m,comp);
    for(int i=1;i<=m;i++) {
        int res=0;
        int j=i;
        while(e[j].val==e[j+1].val) {
            j++;
        }
        for(int k=i;k<=j;k++) {
            int fx=find(e[k].x);
            int fy=find(e[k].y);
            if (fx!=fy) {
                res++;
            }
        }
        for(int k=i;k<=j;k++) {
            int fx=find(e[k].x);
            int fy=find(e[k].y);
            if (fx!=fy) {
                merge(fx,fy);
                res--;
            }
        }
        i=j;
        ans+=res;
    }
    printf("%d\n",ans);
    return 0;
}

Author: tt66ea

Created: 2021-01-22 周五 19:20

Validate

posted @ 2021-01-22 19:24  tt66ea蒟蒻  阅读(80)  评论(0编辑  收藏  举报