本算法是对《算法导论》相关章节伪代码的实现:
这是第一次写的:
#include<iostream>
#include<fstream>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAX 32767
ifstream fin("data.in");
struct node
{
node(int x1,int y1,int len1):x(x1),y(y1),len(len1){}
int x;
int y;
int len;
};
int N,M;
int u,v,l;
int graph[1000][1000],p[1000],state[1000];
node* waittochose[1000000];
int cnt=0;
void heapify(int pos)
{
int l,r,min;
l=pos*2;
r=pos*2+1;
min=pos;
if(l<=cnt&&waittochose[l]->len<waittochose[min]->len)
min=l;
if(r<=cnt&&waittochose[r]->len<waittochose[min]->len)
min=r;
if(min!=pos)
{
swap(waittochose[min],waittochose[pos]);
heapify(min);
}
}
void insert(int x,int y,int len)
{
node* nd=new node(x,y,len);
int cur=++cnt;
waittochose[cur]=nd;
int p=floor(cur/2);
while(p>0&&waittochose[p]->len>waittochose[cur]->len)
{
swap(waittochose[p],waittochose[cur]);
cur=p;
p=floor(cur/2);
}
}
node* extractMin()
{
if(cnt>0)
{
swap(waittochose[1],waittochose[cnt]);
--cnt;
heapify(1);
return waittochose[cnt+1];
}
return NULL;
}
int main()
{
long long length=0;
fin>>N>>M;
for(int i=0;i<N;++i)
{
for(int j=0;j<N;++j)
graph[i][j]=MAX;
graph[i][i]=0;
p[i]=-1;
state[i]=0;
}
for(int i=0;i<M;++i)
{
fin>>u>>v>>l;
graph[u][v]=l;
}
p[0]=0;
state[0]=1;
for(int i=1;i<N;++i)
{
p[i]=0;
if(graph[0][i]<MAX&&graph[0][i]>0)
{
insert(0,i,graph[0][i]);
}
}
node* curnode=NULL;
while(cnt>0)
{
curnode=extractMin();
while(curnode!=NULL&&state[curnode->y]!=0)
{
delete curnode;
curnode=extractMin();
}
if(curnode!=NULL)
{
for(int i=0;i<N;++i)
{
if(state[i]==0&&graph[curnode->y][i]<MAX&&graph[curnode->y][i]>0)
{
insert(curnode->y,i,graph[curnode->y][i]);
if(graph[curnode->y][i]<graph[p[i]][i])
p[i]=curnode->y;
}
}
state[curnode->y]=1;
length+=curnode->len;
delete curnode;
curnode=NULL;
}
}
cout<<length<<endl;
return 0;
}
连接的路径为:a-->b,a-->h,h-->g,g-->f,f-->c,c-->i,c-->d,d-->e
和算法导论上给出的顺序有出入,稍作修改,就一样了,修改的地方为:
void insert(int x,int y,int len)
{
node* nd=new node(x,y,len);
int cur=++cnt;
waittochose[cur]=nd;
int p=floor(cur/2);
while(p>0&&waittochose[p]->len>=waittochose[cur]->len) //这里
{
swap(waittochose[p],waittochose[cur]);
cur=p;
p=floor(cur/2);
}
}
路径为:a-->b,b-->c,c-->i,c-->f,f-->g,g-->h,c-->d,d-->e.就一样了。
Prim算法和Kruskal算法最大的区别在于:Prim算法进行Insert()操作是,起始点已经加入完整的路径中了,这时只要判断结束点在不在路径中,若结束点在路径中(即state[curnode->y]==1),则加入此边会在完整的路径中构成回环,反之则可以加入。而每次extractMin()得到的边的长度可以确定一定是最小的。就可以保证最终结果的最优性了。