1. 程式人生 > >演算法導論25(所有結點對的最短路徑問題)

演算法導論25(所有結點對的最短路徑問題)

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;    
}