#最小生成树算法: (Prim)和样例POJ287
简单的说(Prim) 算法就是一一个模板, 记住它的意思还是很容易实现的。
简介一下Prim算法:
int dp[maxn][maxn],dismin[maxn],vis[maxn];
int n,ans;//这里的n,有必要放在这里,而不是int main()中,要不然prim()中无法操作,会报错
void prim()
{
ans=0;
int i,j,k;
memset(vis,0,sizeof(vis));/*这个步骤对应的是多组数据输入时,
有必要的把原来已经使用了的vis[maxn]清0,重新初始化;*/
double minn;
vis[1]=1;
for(i=1;i<=n;i++)
if(vis[i]!=1){
dismin[i]=dp[1][i];//把要比较的边权存进这个临时数组
}
for(i=1;i<n;i++)
{
minn=INF;//初始化minn很大目的是:保证每次找的的是最小边权而不是minn本身
for(j=1;j<=n;j++)
if(dismin[j]<minn&&vis[j]!=1)
minn=dismin[j],k=j;
ans+=minn;
vis[k]=1;//对i点标记,保证在后面的操作中不会再被操作
for(j=1;j<=n;j++)
if(dismin[j]>dp[k][j]&&vis[j]!=1) dismin[j]=dp[k][j];//更新临时数组,这步骤很重要
}
cout<<ans<<endl;
}
先标记1这个节点。
在一个二维数组中从遍历第一列找到与1相连的节点且要求该边为与1这个点这些相连的边的最小值;换句话说就是找到与1相连的最小边权,该节点为x1。
X1节点被标记,vis[maxn]用来标记的数组,包含全部的节点。
X1节点走过就不会出现重复走的情况了。再从该X1节点对应的X1列中去搜索最小的边权,重复上述操作。
最后全部的节点都被标记,输出答案,程序结束。
下面让我们一起来看看算法代码
https://vjudge.net/problem/POJ-1287
Networking P1287
题目我就不放上去了,链接附上可以自己去看题意再做。
题解代码=Prim算法加一下程序
#include<iostream>
#include<cstring>
using namespace std;
#define maxn 110
#define INF 0x7fffffff
int main()
{
int i,j;
int m;
while(cin>>n){
if(n==0)break;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
dp[i][j]=INF;//对图的初始化
cin>>m;
for(i=1;i<=m;i++)
{int x,y,num;
cin>>x>>y>>num;
if(num<dp[x][y])
dp[x][y]=dp[y][x]=num;//构建无向图的边;
}
prim();
}
return 0;
}