25.1最短路径和矩阵乘法
#include<iostream> using namespace std; #define n 20 int L[n][n],M[n][n]; typedef struct { int VNum,ENum; int w[n][n]; }Graph; void create_graph(Graph &G) { int i,j,v1,v2; cin>>G.VNum>>G.ENum; for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++)G.w[i][j]=10000; } for(i=0;i<G.VNum;i++)G.w[i][i]=0; for(i=0;i<G.ENum;i++) { cin>>v1>>v2>>j; G.w[v1][v2]=j; } } int min(int a,int b) { return a<b?a:b; } void extend_shortest_paths(Graph G) { int i,j,k; for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++) { M[i][j]=L[i][0]+G.w[0][j]; for(k=1;k<G.VNum;k++)M[i][j]=min(M[i][j],L[i][k]+G.w[k][j]); } } for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++)L[i][j]=M[i][j]; } } void slow_all_pairs_shortest_paths(Graph G) { int i,j; for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++)L[i][j]=G.w[i][j]; } for(i=1;i<=G.VNum-2;i++)extend_shortest_paths(G); } int main() { int i,j; Graph G; create_graph(G); slow_all_pairs_shortest_paths(G); cout<<"++++++++++++++++++++"<<endl; for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++)cout<<L[i][j]<<' '; cout<<endl; } return 0; }
#include<iostream> using namespace std; #define n 20 int L[n][n],M[n][n]; typedef struct { int VNum,ENum; int w[n][n]; }Graph; void create_graph(Graph &G) { int i,j,v1,v2; cin>>G.VNum>>G.ENum; for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++)G.w[i][j]=10000; } for(i=0;i<G.VNum;i++)G.w[i][i]=0; for(i=0;i<G.ENum;i++) { cin>>v1>>v2>>j; G.w[v1][v2]=j; } } int min(int a,int b) { return a<b?a:b; } void extend_shortest_paths(Graph G) { int i,j,k; for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++) { M[i][j]=L[i][0]+L[0][j]; for(k=1;k<G.VNum;k++)M[i][j]=min(M[i][j],L[i][k]+L[k][j]); } } for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++)L[i][j]=M[i][j]; } } void faster_all_pairs_shortest_paths(Graph G) { int i,j,m=1; for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++)L[i][j]=G.w[i][j]; } while(m<G.VNum-1) { extend_shortest_paths(G); m*=2; } } int main() { int i,j; Graph G; create_graph(G); faster_all_pairs_shortest_paths(G); cout<<"++++++++++++++++++++"<<endl; for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++)cout<<L[i][j]<<' '; cout<<endl; } return 0; }25.2Floyd-Warshall算法
#include<iostream> using namespace std; #define n 20 int d[n][n]; typedef struct { int VNum,ENum; int w[n][n]; }Graph; void create_graph(Graph &G) { int i,j,v1,v2; cin>>G.VNum>>G.ENum; for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++)G.w[i][j]=10000; } for(i=0;i<G.VNum;i++)G.w[i][i]=0; for(i=0;i<G.ENum;i++) { cin>>v1>>v2>>j; G.w[v1][v2]=j; } } int min(int &a,int &b) { return a<b?a:b; } void Floyd_Warshall(Graph G) { int i,j,k; for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++)d[i][j]=G.w[i][j]; } for(k=0;k<G.VNum;k++) { for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++)d[i][j]=min(d[i][j],d[i][k]+d[k][j]); } } } int main() { int i,j; Graph G; create_graph(G); Floyd_Warshall(G); cout<<"++++++++++++++++++++"<<endl; for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++)cout<<d[i][j]<<' '; cout<<endl; } return 0; }
25.3用于稀疏图的Johnson算法
#include<iostream> using namespace std; #define n 20 int dist1[n],dist2[n],d[n],D[n][n]; typedef struct ENode { int v,w; ENode *next; }ENode; typedef struct VNode { int u; ENode *next; }VNode; typedef struct { int VNum,ENum; VNode Adj[n]; }Graph; void create_graph(Graph &G) { int i,j,v1,v2; cin>>G.VNum>>G.ENum; for(i=0;i<G.VNum;i++) { G.Adj[i].u=i; G.Adj[i].next=NULL; } for(i=0;i<G.ENum;i++) { cin>>v1>>v2>>j; ENode *p=(ENode *)malloc(sizeof(ENode)); p->v=v2; p->w=j; p->next=G.Adj[v1].next; G.Adj[v1].next=p; } } void initialize_single_source1(Graph G,int s) { for(int i=0;i<G.VNum;i++)dist1[i]=10000; dist1[s]=0; } void relax1(int u,int v,int w) { if(dist1[u]+w<dist1[v])dist1[v]=dist1[u]+w; } bool Bellman_Ford(Graph G,int s) { int i,j; initialize_single_source1(G,s); for(i=1;i<G.VNum;i++) { for(j=0;j<G.VNum;j++) { ENode *p=G.Adj[j].next; while(p) { relax1(G.Adj[j].u,p->v,p->w); p=p->next; } } } for(j=0;j<G.VNum;j++) { ENode *p=G.Adj[j].next; while(p) { if(dist1[G.Adj[j].u]+p->w<dist1[p->v])return false; p=p->next; } } return true; } void initialize_single_source2(Graph G,int s) { for(int i=0;i<G.VNum;i++)dist2[i]=10000; dist2[s]=0; } void relax2(int u,int v,int w) { if(dist2[u]+w<dist2[v]) { dist2[v]=dist2[u]+w; d[v]=dist2[v]; } } void Dijkstra(Graph G,int s) { int i,j,k,min; initialize_single_source2(G,s); for(i=0;i<G.VNum;i++)d[i]=dist2[i]; for(i=0;i<G.VNum;i++) { min=d[0],j=0; for(k=1;k<G.VNum;k++) { if(d[k]<min) { min=d[k]; j=k; } } d[j]=10001; ENode *p=G.Adj[j].next; while(p) { relax2(G.Adj[j].u,p->v,p->w); p=p->next; } } } void Johnson(Graph G) { int i,j; Graph H=G; H.Adj[G.VNum].u=G.VNum; H.Adj[G.VNum].next=NULL; for(i=0;i<G.VNum;i++) { ENode *p=(ENode *)malloc(sizeof(ENode)); p->v=i; p->w=0; p->next=H.Adj[G.VNum].next; H.Adj[G.VNum].next=p; } H.VNum++; if(!Bellman_Ford(H,G.VNum))cout<<"the input graph contains a negative-weight cycle"<<endl; else { for(i=0;i<=G.VNum;i++) { ENode *p=H.Adj[i].next; while(p) { p->w=p->w+dist1[i]-dist1[p->v]; p=p->next; } } H.VNum--; for(i=0;i<G.VNum;i++) { Dijkstra(H,i); for(j=0;j<G.VNum;j++)D[i][j]=dist2[j]+dist1[j]-dist1[i]; } } } int main() { int i,j; Graph G; create_graph(G); Johnson(G); cout<<"++++++++++++++++++++"<<endl; for(i=0;i<G.VNum;i++) { for(j=0;j<G.VNum;j++)cout<<D[i][j]<<' '; cout<<endl; } return 0; }