图算法专题(二)最短路径

一、Dijkstra算法

 问题一:

图算法专题(二)最短路径

输入:

6 8 0
0 1 1
0 3 4
0 4 4
1 3 2
2 5 1
3 2 2
3 4 3
4 5 3

输出:

0 1 5 3 4 6

代码:

(1)邻接矩阵

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;

#define maxn 100
#define INF 0x3f3f3f3f

void dij(int s);

int n,m,s;
int G[maxn][maxn],d[maxn];
bool vis[maxn]={false};


int main(){
    cin>>n>>m>>s;
    memset(G,INF,sizeof(G));
    for(int i=0;i<m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        G[x][y]=z;
    }
    dij(s);
    for(int i=0;i<n;i++){
        cout<<d[i]<<" ";
    }
    cout<<endl;
    return 0;
}

void dij(int s){
    memset(d,INF,sizeof(d));
    d[s] = 0;
    for(int i=0;i<n;i++){
        int u = -1,MIN = INF;
        for(int j=0;j<n;j++){
            if(vis[j]==false&&d[j]<MIN){
                u = j;
                MIN = d[j];
            }
        }
        if(u==-1){
            return;    
        }
        vis[u] = true;
        for(int v=0;v<n;v++){
            if(vis[v]==false&&G[u][v]!=INF&&d[u]+G[u][v]<d[v]){
                d[v] = d[u]+G[u][v];
            }
        }
    }
}

(2)邻接表

#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;

#define maxn 100
#define INF 0x3f3f3f3f

struct node{
    int v,vis;
};

void dij(int s);

int n,m,s;
int d[maxn];
vector<node> adj[maxn];
bool vis[maxn]={false};


int main(){
    cin>>n>>m>>s;
    for(int i=0;i<n;i++){
        adj[i].clear();
    }
    for(int i=0;i<m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        node temp;
        temp.v = y;
        temp.vis = z;
        adj[x].push_back(temp);
    }
    dij(s);
    for(int i=0;i<n;i++){
        cout<<d[i]<<" ";
    }
    cout<<endl;
    system("pause");
    return 0;
}

void dij(int s){
    memset(d,INF,sizeof(d));
    d[s] = 0;
    for(int i=0;i<n;i++){
        int u=-1,MIN = INF;
        for(int j=0;j<n;j++){
            if(vis[j]==false&&d[j]<MIN){
                u = j;
                MIN = d[j];
            }
        }
        if(u==-1){
            return;
        }
        vis[u]=true;
        for(int j=0;j<(int)adj[u].size();j++){
            int v = adj[u][j].v;
            if(vis[v]==false&&adj[u][j].vis+d[u]<d[v]){
                d[v]=adj[u][j].vis+d[u];
            }
        }
    }
}

 问题二:最短路

在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?

Input:输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。
Output:对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间

Sample Input

2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0

Sample Output

3
2

代码:

(1)邻接矩阵

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;

#define maxn 105
#define INF 0x3f3f3f3f

void dij(int s);

int G[maxn][maxn];
bool vis[maxn];
int d[maxn];
int n,m;
int main(){
    while(cin>>n>>m){
        if(n==0&&m==0){
            break;
        }
        memset(G,INF,sizeof(G));
        for(int i=0;i<m;i++){
            int x,y,z;
            cin>>x>>y>>z;
            G[x][y] = G[y][x] = z;
        }
        dij(1);
        cout<<d[n]<<endl;
    }
    return 0;
}

void dij(int s){
    for(int i=1;i<=n;i++){
        d[i]=G[1][i];
        vis[i] = false;
    }
    d[s]=0;
    for(int i=1;i<=n;i++){
        int u=-1,MIN = INF;
        for(int j=1;j<=n;j++){
            if(vis[j]==false&&d[j]<MIN){
                u = j;
                MIN = d[j];
            }
        }
        if(u==-1){
            return;
        }
        vis[u]=true;
        for(int v=1;v<=n;v++){
            if(vis[v]==false&&G[u][v]!=INF&&G[u][v]+d[u]<d[v]){
                d[v]= G[u][v]+d[u];
            }
        }
    }
}

(2)邻接表

#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;

#define maxn 105
#define INF 0x3f3f3f3f

struct node{
    int v,vis;
};

void dij(int s);

vector<node> adj[maxn];
bool vis[maxn];
int d[maxn];
int n,m;
int main(){
    while(cin>>n>>m){
        if(n==0&&m==0){
            break;
        }
        for(int i=0;i<n;i++){
            adj[i].clear();
        }
        for(int i=0;i<m;i++){
            int x,y,z;
            cin>>x>>y>>z;
            node temp;
            temp.vis = z;
            temp.v = y;
            adj[x].push_back(temp);
            temp.v = x;
            adj[y].push_back(temp);
        }
        dij(1);
        cout<<d[n]<<endl;
    }
    return 0;
}

void dij(int s){
    memset(d,INF,sizeof(d));
    for(int i=1;i<=n;i++){
        vis[i]=false;
    }
    d[s]=0;
    for(int i=1;i<=n;i++){
        int u=-1,MIN = INF;
        for(int j=1;j<=n;j++){
            if(vis[j]==false&&d[j]<MIN){
                u = j;
                MIN = d[j];
            }
        }
        if(u==-1){
            return;
        }
        vis[u]=true;
        for(int j=0;j<(int)adj[u].size();j++){
            int v = adj[u][j].v;
            if(vis[v]==false&&adj[u][j].vis+d[u]<d[v]){
                d[v] = adj[u][j].vis+d[u];
            }
        }
    }
}

 二、Floyd算法

问题同最短路

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 105;
#define INF 0x3f3f3f3f
int a[maxn][maxn];
int n,m;

void floyd();

int main(){
    while(cin>>n>>m){
        if(n==0&&m==0){
            break;
        }
        memset(a,INF,sizeof(a));
        while(m--){
            int x,y,z;
            cin>>x>>y>>z;
            a[x][y]=a[y][x]=z;
        }
        floyd();
    }
    return 0;
}

void floyd(){
    int s=1;
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            if(a[i][k]!=INF){
                for(int j=1;j<=n;j++){
                    if(a[i][j]>a[i][k]+a[k][j]){
                        a[i][j]=a[i][k]+a[k][j];
                    }
                }
            }
        }
    }
    printf("%d\n",a[s][n]);
}

 

上一篇:图论:dij算法优化:双端队列及详细证明


下一篇:利用 uDig 生成 GeoServer 可用的 SLD 渲染文件