zoukankan      html  css  js  c++  java
  • POJ-2387 Til the Cows Come Home

    hyh大佬很热爱学习,他打算偷偷跑回学校学习,为了多学习他希望可以找最快的路线回到学校。
    广州市里有N个(2 <= N <= 1000)个地铁站,编号分别为1..N。zzj家在1号地铁站旁边,五山站是N号地铁站。地铁站之间共有M (1 <= M <= 2000)条双向路径。
    hyh现在在1号地铁站,他希望知道到学校最短要多长时间。可以保证hyh能到达学校。忽略hyh在换乘地铁时需要的等待时间

    Sample Input
    
        5 5
        1 2 20
        2 3 30
        3 4 20
        4 5 20
        1 5 100
    
    Sample Output
    
        90
    

    Dijkstra算法思想:主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。  时间复杂度O(n^2),代码如下:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int maxx = 1005;
    int adj[maxx][maxx]; // 邻接表来存储图的信息
    bool found[maxx];  //标记是否访问过该结点
    int t, n;
    const int inf = 1 << 29;  //记住不要将最大值设成101等,虽然说题目给的边的大小是1 ~ 100 但是输入数据有坑
    
    void init() { // 初始化
        for (int i = 1; i <= n ; ++i) {
            for (int j = 1; j <= n; ++j) {
                adj[i][j] = inf;
            }
        }
        memset(found, false, n + 1);
    }
    
    void dijkstra() {
        int dis[n + 1];
        for (int i = 1; i <= n; ++i) {
            dis[i] = adj[n][i]; // 首先对distance数组进行初始化  我选择的是从结点n到结点1
            // 也可以选择从结点1到结点n
        }
        found[n] = true;
        for (int i = 1; i <= n; ++i) {
            int minv = 0, mind = inf;  //找到在未被访问的结点之中的最小的结点
            for (int j = 1; j <= n; ++j) {
                if (found[j]) continue;
                if (dis[j] < mind) {
                    minv = j;
                    mind = dis[j];
                }
            }
            for (int j = 1; j <= n; ++j) {
                if (adj[minv][j] != inf) {
                    dis[j] = min(dis[j], adj[minv][j] + dis[minv]);  // 对dis进行更新
                }
            }
            found[minv] = true;
        }
        printf("%d
    ", dis[1]);
    }
    
    int main() {
        scanf("%d%d", &t, &n);
        init();
        for (int i = 0; i < t; ++i) {
            int from, to, edge;
            scanf("%d%d%d", &from, &to, &edge);
            adj[from][to] = adj[to][from] = min(adj[from][to], edge); // 去重边
        }
        dijkstra();
        return 0;
    }

    Floyd算法思想:(时间复杂度O(N^3),在此题中会超时,写出来只是供大家学习一下)

    1,从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。
    2,对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短。如果是更新它。
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstdio>
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    int t, n;
    const int maxx = 1005;
    int gra[maxx][maxx], path[maxx][maxx];
    const int inf = 1 << 29;
    
    void floyd() {
        vector<vector<int> > A(n + 1, vector<int>(n + 1));
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                A[i][j] = gra[i][j];
                path[i][j] = -1;
            }
        }
        for (int v = 1; v <= n; ++v) {
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= n; ++j) {
                    if (A[i][j] > A[i][v] + A[v][j]) {
                        A[i][j] = A[i][v] + A[v][j];
                        path[i][j] = v;
                    }
                }
            }
        }
    }
    
    int printPath(int v, int w) {
        if (-1 == path[v][w]) {
            return gra[v][w];
        }
        int mid = path[v][w];
        return printPath(v, mid) + printPath(mid, w);
    }
    
    int main() {
        scanf("%d%d", &t, &n);
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (i != j)
                    gra[i][j] = inf;
            }
        }
    
        for (int i = 0; i < t; ++i) {
            int from, to, edge;
            scanf("%d%d%d", &from, &to, &edge);
            gra[from][to] = gra[to][from] = min(gra[from][to], edge);
        }
        floyd();
        printf("%d
    ", printPath(n, 1));
        return 0;
    }

    相比较可得知Dijkstra算法更优于Floyd算法,但是,Dijkstra算法不能处理负权边而Floyd可以,一般我们可以观察题目给出的数据大小来选择我们解题的算法。

  • 相关阅读:
    sql基础笔记备忘
    论坛---挂掉的思考
    http response
    跑步肋骨下方疼
    Golang
    svn rollback: 恢复到上一版本
    中国时区
    crontab
    初识redis
    siege
  • 原文地址:https://www.cnblogs.com/wxx23-IOU/p/13610812.html
Copyright © 2011-2022 走看看