prim算法
从以判断的点到未判断的点之间的边权中选择一个最小的去连接,直到所有点遍历完或者不能在遍历新的点结束。
code:
#include <iostream>
#include <algorithm>
#define maxn 1000
#define INF 0x3f3f3f
using namespace std;
int n,t;
int m[maxn][maxn];
int prim(){
int ans=0;
int min=INF;
int d[maxn],color[maxn],b[maxn];
for(int i=0;i<n;i++){
color[i]=0;//记录改点是否遍历过
d[i]=m[0][i];//记录初始每个顶点最短路径为到顶点的距离
b[i]=0;//记录他的上一个节点
}
color[0]=1;
for(int i=1;i<n;i++){
min=INF;
int u=-1;
for(int j=0;j<n;j++){
if(!color[j]&&d[j]<min){
min=d[j];
u=j;
}
}
color[u]=1;
cout<<u+1<<" "<<b[u]+1<<endl;
ans+=m[u][b[u]];
for(int j=1;j<n;j++){
if(!color[j]&&m[u][j]<d[j]){
d[j]=m[u][j];
b[j]=u;
}
}
}
return ans;
}
int main(){
n=6;
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
m[i][j]=INF;
}
}
m[0][1]=6,m[0][2]=1,m[0][3]=5;
m[1][0]=6,m[1][2]=5,m[1][4]=3;
m[2][0]=1,m[2][1]=5,m[2][3]=5,m[2][4]=6,m[2][5]=4;
m[3][0]=5,m[3][2]=5,m[3][5]=2;
m[4][1]=3,m[4][2]=6,m[4][5]=6;
m[5][3]=2,m[5][2]=4,m[5][4]=6;
cout<<prim()<<endl;
}
Kruskal算法
先按升序排序边权,然后从小到大的顺序寻找边的两点是否已经连接;
上图的样例
6 10
1 2 6
1 3 1
1 4 5
2 3 5
2 5 3
5 3 6
5 6 6
6 3 4
6 4 2
4 3 5
code :
#include<bits/stdc++.h>
using namespace std;
const int L=1e5+7;
const int inf=0x3f3f3f3f;
const int maxn=1000+7;
int father[maxn],n,m,num[maxn],nPos;//父节点(并查集),点数,边数,最小生成树点集 当前访问方位
struct node{
int s,y,w;//边集,左端点,右端点,权值
}edge[L];
void init(){//初始化并查集
for(int i=0;i<=n;i++)
father[i]=i;
}
int root(int x){//并查集,构造父节点
return father[x]==x?x:father[x]=root(father[x]);
}
void unite(int x,int y){//并查集,合并两个联通图
x=root(x);
y=root(y);
if(x!=y)
father[y]=x;
}
int alike(int x,int y){ //并查集,判断是否为同一连通图
return root(x)==root(y);
}
int cmp(node a,node b){
return a.w<b.w;
}
int kruskal(){//最小生成树
init();
sort(edge,edge+m,cmp); //对边进行权值排序
int sum=0,cnt=0;
for(int i=0;i<m;i++) //每次选择最小且未访问过的一条边
{
if(cnt==n-1)
break;
if(!alike(edge[i].s,edge[i].y)){
unite(edge[i].s,edge[i].y);
cout<<edge[i].s<<" "<<edge[i].y<<endl;
sum+=edge[i].w;
cnt++;
num[++nPos]=i;
}
}
return cnt!=n-1?-1:sum; //判断边是否大于等于n-1,否则输出-1
}
void read(){
scanf("%d %d",&n,&m);
for(int i=0;i<m;i++)
scanf("%d %d %d",&edge[i].s,&edge[i].y,&edge[i].w);
}
void solve(){
nPos=0;
int mst=kruskal();
printf("%d\n",mst);
}
int main(){
read();
solve();
return 0;
}