题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz
。
输入格式
第一行包含两个整数 N,M,表示该图共有 N 个结点和 M 条无向边。
接下来 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
说明/提示
数据规模:
对于 20%20% 的数据,N≤5,M≤20。
对于 40%40% 的数据,N≤50,M≤2500。
对于 70%70% 的数据,N≤500,M≤104。
对于 100%100% 的数据:
1≤N≤5000,1≤M≤2×105,1≤Zi≤104。
样例解释:
所以最小生成树的总边权为 2+2+3=72+2+3=7。
本题笔者用的是最小生成树布鲁克斯算法,其实就是在并查集的基础加了一个快排和一个权值。
而它的算法思想就是按权值大小找边,从权值小的开始找,最得到最小生成树。
#include<stdio.h>
#include<stdlib.h>
int sum=0,t=0;
int a[5001];
struct node
{
int x;
int y;
int z;
};
struct node b[200001];
int cmp(void* a1, void* b1)//快排
{
struct node a = *(struct node*) a1;
struct node b = *(struct node*) b1;
return a.z - b.z;
}
void init(int m);
void merge(int x,int y,int z);
int getf(int z);
int main()
{
int n,m;
scanf("%d%d",&n,&m);
init(n);
for(int i=0;i<m;i++)
scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].z);
qsort(b, m, sizeof(struct node), cmp);
for(int i=0;i<m;i++)
printf("%d %d %d\n",b[i].x,b[i].y,b[i].z);
for(int i=0;i<m;i++)
{
merge(b[i].x,b[i].y,b[i].z);
if(t==n-1)
break;
}
if(t==n-1)//判断是否生成最小树;
printf("%d",sum);
else
printf("orz");
return 0;
}
void init(int m)
{
for(int i=1;i<m;i++)
a[i]=i;
}
void merge(int x,int y,int z)
{
int tx,ty;
tx=getf(x);
ty=getf(y);
if(tx!=ty)
{
a[ty]=tx;
sum+=z;//权值累加
t++;//计入找到的边的个数
}
}
int getf(int i)
{
if(a[i]==i)
return i;
else
{
a[i]=getf(a[i]);
return a[i];
}
}