下面的图示是我的理解:
#include<bits/stdc++.h>
using namespace std;
int inf=0x7ffffff;
int vst[505];
int d[505];
int g[505][505],n,m,ans=0;
void read()
{
int i,j,x,y,w;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
g[i][j]=inf; //初始化i到j距离。
}
}
for(int i=1;i<=m;i++)
{
cin>>x>>y>>w; //給变赋权。
g[x][y]=g[y][x]=w;
}
}
void prim(int v0)
{
int i,j,k,minn;
memset(vst,0,sizeof(vst)); //标记顶点i是否加到生成树中。
for(i=1;i<=n;i++) d[i]=inf; //d[i]表示i与当前生成树中的点的的最小距离。
d[v0]=0;
ans=0;
for(int i=1;i<=n;i++)
{
minn=inf;
for(j=1;j<=n;j++) //选择最小边。
if(vst[j]==0&&minn>d[j]){minn=d[j];k=j;}
vst[k]=1;
ans+=d[k];
for(j=1;j<=n;j++) //更新d[]数组。
{
if(vst[j]==0&&d[j]>g[k][j]) d[j]=g[k][j];
}
}
}
int main()
{
read();
prim(1);
cout<<ans<<endl; //ans为最小生成树,的各条边总和。
return 0;
}
Kruskal 算法;
是一种贪心算法,将边按权排序后,每次从剩下边集选权值最小的,(同时要排除环的情况)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int maxn = 100 + 10;
const int maxm = 100 * 100 + 10;
struct Edge//边
{
int u, v;
int dist;
Edge(int u, int v, int d): u(u), v(v), dist(d) {}
bool operator<(const Edge&rhs)const
{
return dist < rhs.dist;
}
};
struct Kruskal
{
int n, m; //点数,边数
vector<Edge> edges;//边列表
int fa[maxn]; //并查集
int findset(int x){ return fa[x] == -1 ? x : fa[x] = findset(fa[x]); }
void init(int n)
{
this->n = n;
m = 0;
memset(fa, -1, sizeof(fa));
edges.clear();
}
void AddEdge(int u, int v, int dist)
{
edges.push_back(Edge(u, v, dist));
m=edges.size();
}
int kruskal()
{
int sum = 0; //最小生成树权值
int cnt = 0; //最小生成树边数目
sort(edges.begin(), edges.end());
for(int i = 0; i < m; i++)
{
int u = edges[i].u, v = edges[i].v;
if(findset(u) != findset(v)) //判断是不是环。
{
sum += edges[i].dist;
fa[findset(u)] = findset(v);
if(++cnt >= n - 1) break;
}
}
//注意n==0时应该输出0,当最小生成树不存在时,输出-1
return cnt>=n-1?sum:-1;
}
}KK;