Prim算法

来源:互联网 发布:qq网络大型游戏 编辑:程序博客网 时间:2024/05/29 16:49

本算法是对《算法导论》相关章节伪代码的实现:

这是第一次写的:

#include<iostream>#include<fstream>#include<cmath>#include<algorithm>using namespace std;#define MAX 32767ifstream 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()得到的边的长度可以确定一定是最小的。就可以保证最终结果的最优性了。

0 0
原创粉丝点击