N个点M条边的无向连通图,每条边有一个权值,求该图的最小生成树。
Input第1行:2个数N,M中间用空格分隔,N为点的数量,M为边的数量。(2 <= N <= 1000, 1 <= M <= 50000)
第2 - M + 1行:每行3个数S E W,分别表示M条边的2个顶点及权值。(1 <= S, E <= N,1 <= W <= 10000)Output输出最小生成树的所有边的权值之和。Sample Input
9 14
1 2 4
2 3 8
3 4 7
4 5 9
5 6 10
6 7 2
7 8 1
8 9 7
2 8 11
3 9 2
7 9 6
3 6 4
4 6 14
1 8 8
Sample Output
37
#include<bits/stdc++.h>
using namespace std;
#define maxn 50005
#define INF 0x3f3f3f3f
int par[maxn],rank[maxn];
struct edge//边的信息
{
int u,v,cost;
}es[maxn];
bool cmp(edge a,edge b)
{
return a.cost<b.cost;
}
int init(int n)//初始化
{
for(int i=0;i<n;i++)
{
par[i]=i;
rank[i]=1;
}
}
int find(int x)//查询节点函数
{
if(par[x]==x)
{
return x;
}
else
{
return par[x]=find(par[x]);
}
}
void unite(int x,int y)//连接函数
{
x=find(x);
y=find(y);
if(x==y) return ;
if(rank[x]<rank[y])
{
par[x]=y;
}
else
{
par[y]=x;
if(rank[x]==rank[y]);
{
rank[x]++;
}
}
}
bool same(int x,int y)//判断是否 在同一个连通分量里面
{
return find(x)==find(y);
}
int main()
{
int n,m,res=0;
scanf("%d %d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d %d %d",&es[i].u,&es[i].v,&es[i].cost);
}
sort(es,es+m,cmp);//按照权值排序
init(n);//初始化
for(int i=0;i<m;i++)
{
edge e=es[i];
if(!same(e.u,e.v))
{
unite(e.u,e.v);
res+=e.cost;
}
}
printf("%d\n",res);
return 0;
}