一、krustal的优先队列
#include<bits/stdc++.h>
using namespace std;
#define N 1005
#define INF 0x3f3f3f3f
int pre[N];
int n,m;
struct edge
{
int u,v,w;
friend bool operator<(const edge &a,const edge &b)
{
return a.w>b.w;
}
};
int find(int x)
{
if(x!=pre[x])
return pre[x]=find(pre[x]);
return x;
}
void merge(int x,int y)
{
int a=find(x);
int b=find(y);
if(a!=b)
pre[a]=b;
}
void init()
{
for(int i=1;i<=n;i++)
pre[i]=i;
}
int main()
{
cin>>n>>m;
init();
priority_queue<edge>q;
for(int i=0;i<m;i++)
{
int u,v,w;
cin>>u>>v>>w;
q.push({u,v,w});
}
int sum=0;
int cnt=0;
for(int i=0;i<m;i++)
{
auto it=q.top();
q.pop();
//cout<<find(it.u)<<" "<<find(it.v)<<endl;
if(find(it.u)!=find(it.v))
{
merge(it.u,it.v);
sum+=it.w;
cnt++;
}
if(cnt==n-1)
break;
}
//cout<<cnt<<endl;
if(cnt==n-1)
cout<<sum<<endl;
else
cout<<"-1"<<endl;
return 0;
}
二、sort排序,使用结构体存储
#include<bits/stdc++.h>
using namespace std;
const int maxx=2010;
struct s{
int v,w;
int cost;
}t[maxx];
int father[maxx];
bool cmp(s& a1,s& a2){
return a1.cost<a2.cost;
}
int findfather(int x){
while(x!=father[x])
x=father[x];
return x;
}
int kruskal(int n,int m)//n个顶点,m条边数
{
int cnt=0,summ=0;
for(int i=0;i<m;i++){
int a=findfather(t[i].v);
int b=findfather(t[i].w);
if(a!=b){
father[a]=b;
cnt++;
summ+=t[i].cost;
}
if(cnt==n-1) break;
}
if(cnt==n-1) return summ;
return -1;
}
int main()
{
for(int i=0;i<maxx;i++)
father[i]=i;
int n,m;
cin>>n>>m;
for(int i=0;i<m;i++)
cin>>t[i].v>>t[i].w>>t[i].cost;
sort(t,t+m,cmp);
cout<<kruskal(n,m);
return 0;
}
三、prim算法
#include<iostream>
#include<algorithm>
const int MAXN = 1005;
const int INF = 0x3f3f3f3f;
using namespace std;
int Graph[1005][1005];
int d[1005];
bool Visited[1005] = { false };
int n, m;
int Prim();
int FindMin();
int main()
{
int a, b, c;
cin >> n >> m;
fill(Graph[0], Graph[0] + 1005*1005, INF); //初始化图
while (m--) //建图
{
cin >> a >> b >> c;
Graph[a][b] = Graph[b][a] = c; //无向图
}
int ans = Prim();
cout << ans;
return 0;
}
int Prim()
{
fill(d, d + MAXN, INF); //将d数组初始化
d[1] = 0; //将第一个顶点作为起点,用其他点最终答案都一样,只是生成的图形状不一样,但权值都一样
int ans = 0; //记录权值之和
for (int i = 1; i <= n; i++) //注意这里的下标,数字下标,且从0开始。
{
int u = FindMin(); //找到未访问的d[]中最小的权值
if (u == -1) return -1; //如果找不到小于INF的d[u], 则说明剩下的点和集合S不连通
Visited[u] = true;
ans += d[u]; //找到最小的权值路累加起来。
for (int v = 1; v <= n; v++)
if (!Visited[v] && Graph[u][v] != INF && Graph[u][v] < d[v])//如果没有访问过,而且u能到达v,以u作为中介能找到更短的边
d[v] = Graph[u][v]; //更新d数组
}
return ans;
}
int FindMin()
{
int ret = -1;
int MIN = INF;
for (int i = 1; i <= n; i++)
{
if (!Visited[i] && d[i] < MIN)
{
ret = i;
MIN = d[i];
}
}
return ret;
}