模板
Prim算法:设G =(V,E)是无向连通带权图,在生成树的过程中,把已经在生成树中的结点看作一个集合(U),把剩下的结点看作另一个集合(V-U),从连接两个集合的边中选择一条权值最小的边即可,直到U = V。
时间复杂度为:O(n*n)
空间复杂度:O(n)
适用于稠密图
#include<stdio.h>
#include<string.h>
const int INF = 0x3f3f3f3f;
const int MAXN = 105;
bool vis[MAXN];
int c[MAXN][MAXN];
int lowc[MAXN]; //记录初始点到各点的最小权值
int n;
int Prim()
{
int ans = 0;
memset(vis,false,sizeof(vis));
vis[1] = true; //将1加入U集合中
for(int i = 1; i <= n; i++) //初始化,c[1][i]为初始点1到i的最小权值,若没有,则初始化为INF
lowc[i] = c[1][i];
for(int i = 2; i <= n; i++)
{
int minc = INF;
int p = -1;
for(int j = 1; j <= n; j++) //在集合V-U中寻找距离集合U最进的顶点p
if(!vis[j] && minc > lowc[j])
{
minc = lowc[j];
p = j;
}
if(minc == INF) return -1; //图不连通
ans += minc; //最小权值累加
vis[p] = true;
for(int j = 1; j <= n; j++) //找到p点后更新lowc[i]的值
if(!vis[j] && lowc[j] > c[p][j])
lowc[j] = c[p][j];
}
return ans;
}
int main()
{
while(~scanf("%d",&n) && n)
{
int a,b,d;
memset(c,INF,sizeof(c));
for(int i = 1; i <= n*(n-1)/2; i++)
{
scanf("%d%d%d",&a,&b,&d);
c[a][b] = d;
c[b][a] = d;
}
printf("%d\n",Prim());
}
return 0;
}