标签:就是 包含 += get 模板 const ref 连通 sum
最小生成树就是在一个图中寻找一个联通图,必须包含原图的所有节点,且这个图的所有边的权值和最小.
为什么是一个树呢?因为只要求联通,就一定没有环,没有环不就是树了嘛!
Kruskal算法的核心是加边和判环.一条一条把边加上,如果加上会形成环就不加,最后弄成一个连通图.
假设有n个节点,就需要加(n-1)条边.为什么呢?因为每加上一条边,就会多连接一个点.
因为是要求最小生成树,所以先将所有边权值从小到大排序,挨个加边,加完的值一定是最小的.
判环主要用并查集实现,若两个节点的祖先不同,则加边后不会形成环,反之会形成环.
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int n,m,p,sum,father[5005];
struct Edge
{
int x,y,w;
}a[200005];
int getfather(int);
void merge(int,int);
bool cmp(const Edge &a,const Edge &b);
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) father[i]=i;
for(int i=1;i<=m;i++)
{
cin>>a[i].x>>a[i].y>>a[i].w;
}
sort(a+1,a+m+1,cmp);
int k=0;
for(int i=1;i<=m;i++)
{
if(getfather(a[i].x)!=getfather(a[i].y))
{
++k;
merge(a[i].x,a[i].y);
sum+=a[i].w;
}
if(k==n-1) break;
}
cout<<sum;
return 0;
}
int getfather(int v)
{
if(father[v]!=v) father[v]=getfather(father[v]);
return father[v];
}
void merge(int a,int b)
{
father[getfather(a)]=getfather(b);
}
bool cmp(const Edge &a,const Edge &b)
{
return a.w<b.w;
}
核心:加点
(未完待续)
标签:就是 包含 += get 模板 const ref 连通 sum
原文地址:https://www.cnblogs.com/huaruoji/p/12217305.html