学会了一道图的最短路径问题

一道图的最短路径问题

Description

天气逐渐变冷,年老体弱的越越鸟打算去南方某座温度适宜的城市过冬,但由于翅膀严重老化,最远飞行距离有限,请你为可怜的越越鸟计算飞行所需的最短距离,以让它能做好心理准备。

Input

输入包含多组测试数据。

每组输入第一行为两个正整数n(n<=20)和m(m<=n*(n-1)/2),n表示城市个数,m表示线段个数。(线段为两个城市间的连接线)

接下来m行,每行输入三个整数a,b,和l(l<=10^9),表示a市与b市之间存在一条线段,线段长度为l。(a与b不同)

每组最后一行输入两个整数x和y,表示问题:x为越越鸟现在所在的城市,y为越越鸟打算飞往过冬的城市。城市标号为1~n。

Output

对于每组输入,输出x市与y市之间的最短距离,如果x市与y市之间非连通,则输出“No path”。

Samples

input Copy

4 4 1 2 4 1 3 1 1 4 1 2 3 1 2 4

output Copy

3

Dijkstra

迪杰斯特拉算法是用来求一个顶点到其余各顶点的最短路径算法,正好适合这道题

思路

迪杰斯特拉算法中,我们要维护一个found数组,found[i]表示到i点的最短路径是否已经找到,还要维护一个distance数组,distance[i]表示到i点的最短路径。每次从未找到最短路径的点中,找出路径最短的点,然后标记为已找到,再从它出发,探索有没有到其他节点的路径,有路径且比当前的短,就更新distance数组

代码
#include"iostream"
using namespace std;

#define max 1000000000

int graph[50][50];
int find(int dis[], int s[],int n){
    int min=max;
    int minpos=-1;
    for(int i=1; i <= n; i++){
        if(dis[i] < min && s[i]==0){
            min = dis[i];
            minpos = i;
        }
    }
    return minpos;
}
int main(){
    int n,m;
    while(cin>>n>>m) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                graph[i][j] = max;
            }
        }

        for (int i = 1; i <= n; i++) {
            graph[i][i] = 0;
        }

        while (m--) {
            int a, b, l;
            cin >> a >> b >> l;
            graph[a][b] = graph[b][a] = l;
        }
        int x, y;
        cin >> x >> y;
        int dis[n + 1];
        int s[n + 1];
        for (int i = 1; i <= n; i++) {
            dis[i] = graph[x][i];
            s[i]=0;
        }
        int u;
        s[x] = 1;
        while (u = find(dis, s, n), u != -1) {
            s[u] = 1;
            for (int w = 1; w <= n; w++) {
                if (dis[u] + graph[u][w] < dis[w]) {
                    dis[w] = dis[u] + graph[u][w];
                }
            }
        }
        if (dis[y] == max) {
            cout << "No path" << endl;
        } else {
            cout << dis[y] << endl;
        }
    }
}

这个算法的时间复杂度是O(n^2)

Floyd算法

Floyd算法是求图中任意两点之间距离的算法

思路

Floyd算法就是每一次从邻接矩阵中选一个顶点,然后去矩阵中遍历两个顶点i,j,比较i->j的距离和i->k加上k->j的距离

Floyd算法比较暴力,十分好记

#include"iostream"
#include"set"
#include"vector"
#include"algorithm"
using namespace std;


int main(){
    int n,m;
    while(cin>>n>>m) {
        vector<vector<int> > graph(n + 1, vector<int>(n + 1));
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (i != j)graph[i][j] = 1000000000;
                else graph[i][j] = 0;
            }
        }
        while (m--) {
            int a, b, l;
            cin >> a >> b >> l;
            graph[a][b] = graph[b][a] = l;
        }
        for (int k = 1; k <= n; k++) {
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    if (graph[i][j] > graph[i][k] + graph[k][j]) {
                        graph[i][j] = graph[i][k] + graph[k][j];
                    }
                }
            }
        }
        int x, y;
        cin >> x >> y;
        if (graph[x][y] == 1000000000) {
            cout << "No path" << endl;
        } else {
            cout << graph[x][y] << endl;
        }
    }
}

这三个for循环告诉我们,他的时间复杂度是O(n^3),虽然慢了点,但是好记呀。

posted @ 2022-01-02 11:59  博客是个啥?  阅读(186)  评论(0编辑  收藏  举报