usaco2.4 comehome 最短路 Floyd, Dijkstra, Dijkstra优先队列优化

本文对比了Floyd、Dijkstra及优先队列优化的Dijkstra三种算法在解决最短路径问题上的实现方式,并通过具体实例展示了每种算法的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接


水题,求到某一个点的最短路


(第一发还写跪了...)


后来觉得需要练练手(?并不能起到什么作用)于是分别写了Floyd,Dijkstra以及Dijkstra堆优化(即优先队列)的


Floyd

/*
PROB:comehome
LANG:C++
ID:fan_0111
*/
#include <iostream>
#include <cstdio>
#include <cctype>
typedef long long LL;
LL a[100][100];
using namespace std;
int tran(char ch) {
    if (isupper(ch)) return ch - 'A';
    else return ch - 'a' + 26;
}
int main() {
    freopen("comehome.in", "r", stdin);
    freopen("comehome.out", "w", stdout);
    int n;
    scanf("%d\n", &n);
    for (int i = 0; i < n; ++i) {
        char ch1, ch2; int d;
        scanf("%c %c%d\n", &ch1, &ch2, &d);
        if (ch1 == ch2) continue;
        int x1 = tran(ch1), x2 = tran(ch2);
//        printf("%c %c\n", ch1, ch2);
        if (a[x1][x2] == 0 || a[x1][x2] > d) a[x1][x2] = a[x2][x1] = d;
//        printf("a[%d][%d] = %d\n", x1, x2, a[x1][x2]);
    }
    const int tot = 52;


    for (int k = 0; k < tot; ++k) {
        for (int i = 0; i < tot; ++i) {
            for (int j = i + 1; j < tot; ++j) {
                if (a[i][k] != 0 && a[k][j] != 0 && (a[i][j] == 0 || a[i][j] > a[i][k] + a[k][j])) {
                    a[j][i] = a[i][j] = a[i][k] + a[k][j];
                }
            }
        }
    }

    int p;

    int maxD = 1e9;
    for (int i = 0; i < 25; ++i) {
        if (a[i][25] != 0 && a[i][25] < maxD) { p = i; maxD = a[i][25]; }
    }
    printf("%c %lld\n", 'A' + p, a[p][25]);
    return 0;
}


Dijkstra

/*
PROB:comehome
LANG:C++
ID:fan_0111
*/
#include <iostream>
#include <cstdio>
#include <cctype>
#define MAX 60000
typedef long long LL;
const int tot = 52;
int a[100][100], dist[100];
bool vis[60];
using namespace std;
int tran(char ch) {
    if (isupper(ch)) return ch - 'A';
    else return ch - 'a' + 26;
}
int main() {
    freopen("comehome.in", "r", stdin);
    freopen("comehome.out", "w", stdout);
    int n;
    scanf("%d\n", &n);
    for (int i = 0; i < n; ++i) {
        char ch1, ch2; int d;
        scanf("%c %c%d\n", &ch1, &ch2, &d);
        if (ch1 == ch2) continue;
        int x1 = tran(ch1), x2 = tran(ch2);
        if (a[x1][x2] == 0 || a[x1][x2] > d) a[x1][x2] = a[x2][x1] = d;
    }
    int src = 25;
    for (int cnt = 0; cnt < tot - 1; ++cnt) {
        int minD = MAX, p;
        for (int i = 0; i < tot; ++i) {
            dist[i] = a[src][i];
            if (!vis[i] && dist[i] != 0 && dist[i] < minD) {
                minD = dist[i];
                p = i;
            }
        }
        vis[p] = true;
        for (int i = 0; i < tot; ++i) {
            if (i != src && a[p][i] != 0 && (a[src][i] == 0 || a[src][i] > a[src][p] + a[p][i])) a[src][i] = a[i][src] = a[src][p] + a[p][i];
        }
    }
    int p, minD = MAX;
    for (int i = 0; i < 25; ++i) {
//        printf("%d\n", a[src][i]);
        if (a[src][i] != 0 && a[src][i] < minD) { p = i; minD = a[src][i]; }
    }
    printf("%c %d\n", 'A' + p, a[src][p]);
    return 0;
}


优先队列

/*
PROB:comehome
LANG:C++
ID:fan_0111
*/
#include <iostream>
#include <cstdio>
#include <cctype>
#include <queue>
#define MAX 60000
typedef long long LL;
const int tot = 52;
int a[100][100], dist[100];
bool vis[60];
using namespace std;
int tran(char ch) {
    if (isupper(ch)) return ch - 'A';
    else return ch - 'a' + 26;
}
struct qnode {
    int v, c;
    qnode(int vv = 0, int cc = 0) : v(vv), c(cc) {}
    bool operator < (const qnode& node) const { return c > node.c; }
};
priority_queue<qnode> que;
int main() {
    freopen("comehome.in", "r", stdin);
    freopen("comehome.out", "w", stdout);
    int n;
    scanf("%d\n", &n);
    for (int i = 0; i < n; ++i) {
        char ch1, ch2; int d;
        scanf("%c %c%d\n", &ch1, &ch2, &d);
        if (ch1 == ch2) continue;
        int x1 = tran(ch1), x2 = tran(ch2);
        if (a[x1][x2] == 0 || a[x1][x2] > d) a[x1][x2] = a[x2][x1] = d;
    }
    int src = 25;
    vis[src] = true;
    for (int i = 1; i < tot; ++i) {
        for (int j = 0; j < tot; ++j) {
            if (a[src][j] == 0) continue;
            if (!vis[j] && (dist[j] == 0 || dist[j] > dist[src] + a[src][j])) {
                dist[j] = dist[src] + a[src][j];
                que.push(qnode(j, dist[j]));
            }
        }
        while (!que.empty() && vis[que.top().v]) que.pop();
        if (que.empty()) break;
        vis[src = que.top().v] = true;
    }
    int minD = MAX, p;
    for (int i = 0; i < 26; ++i) {
        if (dist[i] != 0 && dist[i] < minD) { minD = dist[i]; p = i; }
    }
    printf("%c %d\n", 'A' + p, dist[p]);
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值