1. 程式人生 > >ACM經典演算法之圖論

ACM經典演算法之圖論

一、(Prim演算法求最小生成樹)

語法:prim(Graph G,int vcount,int father[]);

引數:

G:

圖,用鄰接矩陣表示

vcount:

表示圖的頂點個數

father[]:

用來記錄每個節點的父節點

返回值:

null

注意:

常數max_vertexes為圖最大節點數

常數infinity為無窮大

源程式:

#define infinity 1000000#define max_vertexes 5 typedefint Graph[max_vertexes][max_vertexes];

void prim(Graph G,int vcount,int father[]){int i,j,k;int lowcost[max_vertexes],closeset[max_vertexes],used[max_vertexes];for (i=0;i<vcount;i++)        {        lowcost[i]=G[0][i];        closeset[i]=0;         used[i]=0;        father[i]=-1;         }    used[0]=1; for (i=1;i<vcount;i++)        {        j=0;
while (used[j]) j++;for (k=0;k<vcount;k++)if ((!used[k])&&(lowcost[k]<lowcost[j])) j=k;        father[j]=closeset[j];         used[j]=1;for (k=0;k<vcount;k++)if (!used[k]&&(G[j][k]<lowcost[k]))                { lowcost[k]=G[j][k];                closeset[k]=j; }        }}


二、(Dijkstra演算法求單源最短路徑)

語法:result=Dijkstra(Graph G,int n,int s,int t, int path[]);

引數:

G:

圖,用鄰接矩陣表示

n:

圖的頂點個數

s:

開始節點

t:

目標節點

path[]:

用於返回由開始節點到目標節點的路徑

返回值:

最短路徑長度

注意:

輸入的圖的權必須非負

頂點標號從0開始

用如下方法列印路徑:    i=t;while (i!=s)        {        printf("%d<--",i+1);        i=path[i];        }    printf("%d\n",s+1); 

源程式:

int Dijkstra(Graph G,int n,int s,int t, int path[]){int i,j,w,minc,d[max_vertexes],mark[max_vertexes];for (i=0;i<n;i++) mark[i]=0;for (i=0;i<n;i++)        { d[i]=G[s][i];        path[i]=s; }    mark[s]=1;path[s]=0;d[s]=0;for (i=1;i<n;i++)        {       minc=infinity;        w=0;for (j=0;j<n;j++)if ((mark[j]==0)&&(minc>=d[j])) {minc=d[j];w=j;}        mark[w]=1;for (j=0;j<n;j++)if ((mark[j]==0)&&(G[w][j]!=infinity)&&(d[j]>d[w]+G[w][j]))            { d[j]=d[w]+G[w][j];            path[j]=w; }        }return d[t];}


三、(Bellman-ford演算法求單源最短路徑)

語法:result=Bellman_ford(Graph G,int n,int s,int t,int path[],int success);

引數:

G:

圖,用鄰接矩陣表示

n:

圖的頂點個數

s:

開始節點

t:

目標節點

path[]:

用於返回由開始節點到目標節點的路徑

success:

函式是否執行成功

返回值:

最短路徑長度

注意:

輸入的圖的權可以為負,如果存在一個從源點可達的權為負的迴路則success=0

頂點標號從0開始

用如下方法列印路徑:    i=t;while (i!=s)        {        printf("%d<--",i+1);        i=path[i];        }    printf("%d\n",s+1); 

源程式:

int Bellman_ford(Graph G,int n,int s,int t,int path[],int success){int i,j,k,d[max_vertexes];for (i=0;i<n;i++) {d[i]=infinity;path[i]=0;}    d[s]=0;for (k=1;k<n;k++)for (i=0;i<n;i++)for (j=0;j<n;j++)if (d[j]>d[i]+G[i][j]) {d[j]=d[i]+G[i][j];path[j]=i;}    success=0;for (i=0;i<n;i++)for (j=0;j<n;j++)if (d[j]>d[i]+G[i][j]) return 0;    success=1;return d[t];}


四、(Floyd-Warshall演算法求每對節點間最短路徑)

語法:Floyd_Washall(Graph G,int n,Graph D,Graph P);

引數:

G:

圖,用鄰接矩陣表示

n:

圖的頂點個數

D:

D[i,j]表示從i到j的最短距離

P:

P[i,j]表示從i到j的最短路徑上j 的父節點 

返回值:

null

源程式:

void Floyd_Washall(Graph G,int n,Graph D,Graph P){int i,j,k;for (i=0;i<n;i++)for (j=0;j<n;j++)            { D[i][j]=G[i][j];                P[i][j]=i; }for (i=0;i<n;i++) { D[i][i]=0;P[i][i]=0; }for (k=0;k<n;k++)for (i=0;i<n;i++)for (j=0;j<n;j++)if (D[i][j]>D[i][k]+D[k][j])                    { D[i][j]=D[i][k]+D[k][j];                        P[i][j]=P[k][j]; }}