最小生成树的Prime算法的基本思想是贪心,时间复杂度为O(n^2).
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
const int N = 1005;
const int INF = 1<<30;
bool vis[N];
int dist[N];
int map[N][N];
int n,m;
void Init()
{
memset(vis,0,sizeof(vis));
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
map[i][j] = INF;
}
int Prime(int map[][N],int n)
{
int ans = 0;
for(int i=1; i<=n; i++)
dist[i] = map[1][i];
vis[1] = 1;
for(int i=1; i<=n; i++)
{
int k = 0;
int minval = INF;
for(int j=1; j<=n; j++)
{
if(!vis[j] && dist[j] < minval)
{
minval = dist[j];
k = j;
}
}
vis[k] = 1;
ans += dist[k];
for(int j=1; j<=n; j++)
{
if(!vis[j] && map[k][j] < dist[j])
dist[j] = map[k][j];
}
}
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
Init();
if(n == 0) break;
for(int i=1; i<=m; i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
map[u][v] = w;
map[v][u] = w;
}
printf("%d\n",Prime(map,n));
}
return 0;
}
Prime算法是每次找与当前节点相连的边中权值最小的且边的另一边的节点没有被访问过,然后把它加入到生成树中,直到所
有点都被访问,而kruskal算法则是每次选择没有加入的边中权值最小的且加入后不会形成环,直到形成一棵树为止.
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int N = 1005;
int pre[N],rank[N];
int n,m;
struct Edge
{
int l,r;
int w;
};
Edge edge[N*N];
void Init()
{
for(int i=0;i<N;i++)
{
pre[i] = i;
rank[i] = 1;
}
}
int Find(int x)
{
if(pre[x] != x)
pre[x] = Find(pre[x]);
return pre[x];
}
void Union(int x,int y)
{
x = Find(x);
y = Find(y);
if(x == y) return;
if(rank[x] >= rank[y])
{
pre[y] =x;
rank[x] += rank[y];
}
else
{
pre[x] = y;
rank[y] += rank[x];
}
}
bool cmp(Edge a,Edge b)
{
return a.w < b.w;
}
int Kruskal()
{
Init();
int ans = 0;
sort(edge,edge+m,cmp);
for(int i=0;i<n;i++)
{
int x = Find(edge[i].l);
int y = Find(edge[i].r);
if(x != y)
{
Union(x,y);
ans += edge[i].w;
}
}
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=0;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
edge[i].l = u;
edge[i].r = v;
edge[i].w = w;
}
printf("%d\n",Kruskal());
}
return 0;
}