演算法導論25(所有結點對的最短路徑問題)
阿新 • • 發佈:2019-02-07
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; }
25.2Floyd-Warshall演算法#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; }
#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;
}