Kruskal: 按照边的权值的顺序从小到大查一遍,若不产生圈(重边等),则把当前边加入生成树中。
O(|E|log|V|)
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m;
int fa[10005];
struct bian
{
int f,t,d;
}e[10005];
int cmp(bian a,bian b)
{
return a.d<b.d;
}
int find(int x)
{
if(fa[x]==x) return x;
else return fa[x]=find(fa[x]);
//写法2:return fa[x] == x?x:fa[x] = find(fa[x]);
}
int kru()//通过并查集
{
int ans=0;
sort(e+1,e+m+1,cmp);
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++)
{
int fx=e[i].f , fy=e[i].t;
if(find(fx)!=find(fy)) // ← 能将目前边加上的条件:不在同一个连通分量里
//判环:若有环,则环中的点一定一个fa,即在同一个集合中,则这条边不会加入
//两个点已经加入过了,所以fa一定出相同,若再加上这条边,就会使这两点之间可以相互到达的路径有两条,也就是说形成了回路
{
fa[find(fx)]=find(fy);
ans+=e[i].d;
}
}
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
cin>>e[i].f>>e[i].t>>e[i].d;
printf("%d\n",kru());
return 0;
}
Prim:
int cost[max_v][max_v];//边e=(u,v)的权值(不存在的情况下设为INF)
int mincost[max_v]; //从集合x出发的边到每个顶点的最小权值
bool used[max_v]; //顶点i是否包含在集合x中
int V; //顶点数
int prim()
{
for(int i=0;i<v;i++)
{
mincost[i] = INF;
used[i] = false;
}
mincost[0] = 0;
int res = 0;
while(true)
{
int v=-1;
//从不属于x的顶点中选取从x到其权值最小的顶点
for(int u,int u<v;int u++)
{
if(!used[u] && (v == -1 || mincost[v]<mincost[v]))
v = u;
}
}
if(v == -1) break;
used[v] = true; //把顶点v加入x
res+ = mincost[v]; //把边的长度加到结果里
for(int u=0;u<v;u++)
{
mincost[u]=min(mincost[u],cost[v][u]);
}
return res;
}