A-POJ 2378

比较慢的dijkstra

#include <iostream>
#include <cstring>
#include <vector>
#define INF 0x7f7f7f7f
using namespace::std;

// O(n*n)的dijkstra算法
int N, T; // 2 <= N <= 1000, 1 <= T <= 2000
int dist[1002][1002]; // i到j的边权值
int least[1002]; // 1到各边的最短距离
bool visited[1002]; // 已经得到最小值的节点
int solve() {
    visited[1] = 1;
    int last_index = 1, last_min = 0;
    for (int i = 1; i < N; ++i) { // 最多N-1次
        int cur_min = INF, cur_index; // 获得当前least[]的最小值及对应序号
        for (int j = 2; j <= N; ++j) {
            if (visited[j] == 1) continue; // 跳过已经得到最小值的节点
            least[j] = min(least[j], dist[last_index][j] + last_min);
            if (least[j] < cur_min) {
                cur_min = least[j];
                cur_index = j;
            }
        }
        if (cur_index == N) return least[N]; // 提前找到
        visited[cur_index] = 1;
        last_index = cur_index;
        last_min = cur_min;
    }
    return least[N];
}

int main(void) {
    while (cin >> T >> N) {
        memset(dist, 0x7f, sizeof(int) * 1002 * 1002);
        memset(least, 0x7f, sizeof(int) * 1002); // 0x3f3f3f3f:∞
        memset(visited, 0, sizeof(bool) * 1002);
        for (int t = 1; t <= T; ++t) {
            int p1, p2, d12;
            cin >> p1 >> p2 >> d12;
            // 不是简单图,两个节点之间可能有多条边
            dist[p1][p2] = dist[p2][p1] = min(d12, dist[p1][p2]);
        }
        cout << solve() << endl;
    }
    return 0;
}

使用优先队列优化的dijkstra

#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#define INF 0x7f7f7f7f
using namespace::std;
typedef pair<int, int> pii;

// 使用优先队列优化dijkstra算法
int N, T; // 2 <= N <= 1000, 1 <= T <= 2000
vector<vector<pii>> table(1002, vector<pii>(0)); // [point][<dist, point>]
int least[1002]; // 1到各边的最短距离
bool visited[1002] = { 0 }; // 已经得到最小值的节点
int solve() {
    priority_queue<pii> pqu; // <dist, point>,存dist的相反数,最小的dist会在顶部
    pqu.push(pii(0, 1));
    while (!pqu.empty()) {
        // 每次最小的dist会自动浮上来
        int dist = pqu.top().first, point = pqu.top().second;
        pqu.pop();
        if (visited[point] == 1) continue;
        visited[point] = 1;
        least[point] = -dist;
        if (point == N) return least[point];
        for (int k = 0; k < table[point].size(); ++k) {
            pqu.push(pii(table[point][k].first + dist, table[point][k].second));
        }
    }
    return least[N];
}

int main(void) {
    while (cin >> T >> N) {
        memset(least, 0x7f, sizeof(int) * 1002); // 0x3f3f3f3f:∞
        for (int t = 1; t <= T; ++t) {
            int p1, p2, d12;
            cin >> p1 >> p2 >> d12;
            // 不是简单图,两个节点之间可能有多条边
            table[p1].push_back(pii(-d12, p2));
            table[p2].push_back(pii(-d12, p1));
        }
        cout << solve() << endl;
        vector<vector<pii>>(1002, vector<pii>(0)).swap(table);
        memset(visited, 0, sizeof(bool) * 1002);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值