题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz输入输出格式
输入格式:
第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi
输出格式:
输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz输入输出样例
输入样例#1:
4 51 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出样例#1:
7说明
时空限制:1000ms,128M数据规模:
对于20%的数据:N<=5,M<=20对于40%的数据:N<=50,M<=2500
对于70%的数据:N<=500,M<=10000
对于100%的数据:N<=5000,M<=200000
-----------------------------------------华丽的分界线-----------------------------------------
模板题。
克鲁斯卡尔算法就行。
不过多解释,简单说明一下。
如果你忘记了并查集,赶快恶补。
输入图之后(我按结构体输入的),按边权排序。
从最小的边遍历。
如果两边的点的祖先点不同,这条边算上。
重复,直到已经有n-1条边,完事。
然后,上代码。
当然需要初始化,把自己的祖先设为自己。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
int n;
int m;
struct NODE
{
int u;
int v;
int w;
};
//存图结构体
NODE node[200005];
//习惯单独定义,不单列也行
int fa[5005];
//记录祖先
int ans;
//结果
bool cmp(NODE,NODE);
//比较
int find(int);
//找祖先
bool check();
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&node[i].u,&node[i].v,&node[i].w);
sort(node+1,node+m+1,cmp);
//结构体排序
for(int i=1;i<=n;i++)
fa[i]=i;
//初始化
int tot;
tot=0;
for(int i=1;i<=m;i++)//遍历
{
if(find(node[i].u)!=find(node[i].v))
{
fa[find(node[i].v)]=find(node[i].u);
tot+=node[i].w;
}
}
printf("%d",tot);
return 0;
}
bool cmp(NODE a,NODE b)
{
if(a.w<b.w)
return true;
else
return false;
}
int find(int x)
{
if(fa[x]==x)
return x;
else
return fa[x]=find(fa[x]);
}
bool check()
{
int len;
len=find(1);
for(int i=2;i<=n;i++)
{
if(find(fa[i])==len)
continue;
else
return false;
}
return true;
}