您的位置:首页 > 其它

ACM_Prim算法

2015-07-20 15:38 197 查看
普里姆算法证明:以任意一个顶点作为树的根(这里以1作为根)更新lowcase数组,找到里面最小值,并且这条边一定是最小生成树里面的边(最小生成树要包括所有的顶点,而想要包括这个顶点,只有这几条边,所以一定选择最小的边连接这个顶点)然后以这条边连接的另一个顶点更新lowcase数组,并把该顶点标记为已在树里面,再把已经在树里的点看成一个整体,再找此时lowcase数组里的的最小值,以此类推,直到所有的顶点都被纳入到树里面

普里姆算法的时间复杂度是O(n2)【两层for循环= =】

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define Maxn 110
#define INF 9999999
int maz[Maxn][Maxn],lowcase[Maxn],flag[Maxn];
//maz[i][j]表示i到j的距离,注意无向图和重边!lowcase数组存的是现已在树里的点所能到达的点的最小权值
//flag数组是用来标记某个点是否已经在树里面
int prim(int n)
{
int i,j,ans = 0,pos,mi;
memset(flag,0,sizeof(flag));
for (i = 2; i <= n; ++i)
lowcase[i] = maz[1][i];//先以1作为根节点,更新lowcase数组
lowcase[1] = 0;//为了数组里的值全
flag[1] = 1;//1这个点标记为已在树里面
for (i = 0; i < n-1; ++i)//循环n-1次,每次找一个点纳入到树里面,加上1根节点总共就是n个点
{
mi = INF;//mi为每次在lowcase数组里找到的最小值,所以刚开始赋值成最大值
for (j = 1; j <= n; ++j)
{
if (!flag[j] && lowcase[j] < mi)
{
mi = lowcase[j];
pos = j;
}
}
ans += mi;
flag[pos] = 1;
for (j = 1; j <= n; ++j)//用新的节点更新lowcase数组
{
if (!flag[j] && maz[pos][j] < lowcase[j])
{
lowcase[j] = maz[pos][j];
}
}
}
return ans;
}
int main()
{
int n,i,j;
while (~scanf("%d",&n) && n)
{
for (i = 1; i <= n; ++i)
{
for (j = 1; j <= n; ++j)
maz[i][j] = i == j ? 0 : INF;
}//刚开始得把数组里的数存成无穷大
int a,b,c;
for (i = 0; i < n*(n-1)/2; ++i)
{
scanf("%d%d%d",&a,&b,&c);
if (c < maz[a][b])
maz[a][b] = maz[b][a] = c;//无向图+重边
}
int ans = prim(n);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  普里姆算法 prim