码迷,mamicode.com
首页 > 其他好文 > 详细

POJ-2387 Til the Cows Come Home

时间:2020-09-17 12:30:28      阅读:28      评论:0      收藏:0      [点我收藏+]

标签:span   std   sam   inpu   学习   点距   tar   忽略   开始   

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\n", 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\n", printPath(n, 1));
    return 0;
}

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

POJ-2387 Til the Cows Come Home

标签:span   std   sam   inpu   学习   点距   tar   忽略   开始   

原文地址:https://www.cnblogs.com/yegowxx23/p/13610812.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!