图论基础——并查集

并查集的作用
1.查询元素A和元素B是否属于同一组。
2.合并元素A和元素B所在的组。
例题畅通工程

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#include <vector>
using namespace std;
const int maxn = 20005;
const int inf = 0x3f3f3f3f;
typedef long long ll;
int n,m;
int f[110];
struct node
{
    int x,y,t;
}s[maxn];
int cmp(node a,node b)
{
    return a.t<b.t;
}
int find(int x)  //查找每一个节点的祖先节点。
{
    if(x==f[x])
        return x;
    return f[x]=find(f[x]);//在查找父亲节点的同时进行了状态的压缩使每一个点都连接在祖先节点上。
}
void merge(int a,int b) //实现两个集合的合并
{
    int fa=find(a);
    int fb=find(b);
    if(fa!=fb){  //应该把小的节点合并到大的节点上去,但是听说不会在这里卡人。
        f[fa]=f[fb];
    }
}
int main()
{
    while(~scanf("%d %d",&n,&m)){
        if(n==0)break;
        int ans=0;
        for(int i=1;i<=m;i++)
            f[i]=i;
        for(int i=1;i<=n;i++){
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            s[i].x=a,s[i].y=b,s[i].t=c;
        }
        sort(s+1,s+n+1,cmp);
        for(int i=1;i<=n;i++){  //贪心的找最小的
            int a=find(s[i].x);
            int b=find(s[i].y);
            if(a!=b){
                merge(s[i].x,s[i].y);
                ans+=s[i].t;
            }
        }
        int cnt=0;
        for(int i=1;i<=m;i++){
            if(i==find(i))
                cnt++;
        }
        if(cnt!=1){
            printf("?\n");
        }
        else{
            printf("%d\n",ans);
        }
    }
    return 0;
}

发布了35 篇原创文章 · 获赞 25 · 访问量 836

猜你喜欢

转载自blog.csdn.net/qq_43816599/article/details/96147248
今日推荐