最小生成树 kruskal 并查集

题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz

输入输出格式
输入格式:
第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)
接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi

输出格式:
输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz

输入输出样例
输入样例#1:
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出样例#1:
7

这段代码其实出现了一点小错误,但我实在不知道错在哪。。。
好吧,我后来修改了merge的代码,算是写对了

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
//最小生成树之kruskal 也就是使用并查集
//第一个是判断 边是否在同一个子集之中 第二个就是判断 边之间的合并
int a[100]={0};//
//再创建一个结构体数组来存储 起点,终点 和边的长度
struct jj{
    int x,y,z;
}J[100];
//写一个判断祖宗的方法
int zuzong(int x){
    if(a[x]==x)
        return x;
    else
        return zuzong(a[x]);
}
//写一个判断的方法
bool check(int x,int y){
   return zuzong(x)==zuzong(y);
}

//再写一个合并的方法
void merge_1(int x,int y){
    if(!check(x,y))
    a[zuzong(x)]=zuzong(y);

}
//再写一个比较的方法,用边的长度作为比较对象
bool cmp(jj x,jj y){//名字要取好
    return x.z<y.z;
}
int main()
{
    int N,M;//有n个结点,M条边
    int sum=0;
    int co=0;//这个是记录边数目,也就是能不能生成最小生成树
    int i;
    //先对结点和边进行输入
    scanf("%d%d",&N,&M);
    for(i=0;i<M;i++){
        scanf("%d%d%d",&J[i].x,&J[i].y,&J[i].z);
    }
    //然后按照思想,先对边进行从小到大排序,然后使用并查集对边的顶点进行判断是否在同一个集合中
    sort(J,J+M,cmp);
    //对几个结点的祖宗赋初值,都是等于自己
    for(i=1;i<=N;i++)
        a[i]=i;

    //然后开始判断
    for(i=0;i<M;i++){//从第一条边到最后一条边
        if(!check(J[i].x,J[i].y)){//如果这条边的两个点不在同一个集合,那就合并,并且记录长度
            merge_1(J[i].x,J[i].y);
            sum+=J[i].z;
            co++;
        }
    }

    //最后输出
    if(co==N-1)
        printf("%d",sum);
    else
        printf("orz");

}











发布了72 篇原创文章 · 获赞 5 · 访问量 2809

猜你喜欢

转载自blog.csdn.net/qq_41115379/article/details/104928766