UVA11374-Airport Express(最短路+枚举)

题目链接

http://acm.hust.edu.cn/vjudge/problem/22966

思路

因为商业线只能够选择一次,只需要枚举这K条商业线,设每次选中的一条商业A->B的起点为A,终点为B,则起点到A和B到终点必然选择的是经济线
因此只需要对起点和终点分别做一次dijkstra,设起点到A的时间为f(a), B到终点的时间为g(b),则T = f(a) + g(b) + T(a, b)

细节

  1. 注意路径输出的格式以及换行
  2. 商业线也为双向路径

代码

#include <iostream>
#include <cstring>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <deque>
#include <bitset>
#include <algorithm>
using namespace std;

#define PI acos(-1.0)
#define LL long long
#define PII pair<int, int>
#define PLL pair<LL, LL>
#define mp make_pair
#define IN freopen("in.txt", "r", stdin)
#define OUT freopen("out.txt", "wb", stdout)
#define scan(x) scanf("%d", &x)
#define scan2(x, y) scanf("%d%d", &x, &y)
#define scan3(x, y, z) scanf("%d%d%d", &x, &y, &z)
#define sqr(x) (x) * (x)
#define pr(x) cout << #x << " = " << x << endl
#define lc o << 1
#define rc o << 1 | 1
#define pl() cout << endl

const int maxn = 505;
const int INF = 0x3e3e3e3e;

struct Edge {
    int from, to, dist;
    Edge(int a, int b, int c) : from(a), to(b), dist(c) {

    }
};

struct cmp {
    bool operator() (PII x, PII y) {
        return y.second < x.second;
    }
};

vector<Edge> edges;
vector<int> G[maxn];
vector<Edge> quick;
int n, m, k, S, E, tot = 0;

void init() {
    for (int i = 0; i <= n; i++) G[i].clear();
    quick.clear();
    edges.clear();
    tot = 0;
}

void addedge(int u, int v, int w) {
    edges.push_back(Edge(u, v, w));
    int m = edges.size();
    G[u].push_back(m - 1);
}

void dijkstra(int s, int *d, int *p) {
    bool vis[maxn];
    memset(vis, 0, sizeof(vis));
    fill(d, d + n + 1, INF);
    d[s] = 0;
    p[s] = -1;
    priority_queue<PII, vector<PII>, cmp> Q;
    Q.push(mp(s, 0));
    while (!Q.empty()) {
        PII x = Q.top(); Q.pop();
        int u = x.first;
        if (vis[u]) continue;
        vis[u] = 1;
        for (int i = 0; i < G[u].size(); i++) {
            Edge &e = edges[G[u][i]];
            int v = e.to;
            if (d[v] > d[u] + e.dist) {
                d[v] = d[u] + e.dist;
                Q.push(mp(v, d[v]));
                p[v] = u;
            }
        }
    }
}


void print_path(int x, int *p) {
    if (x == -1) return;
    print_path(p[x], p);
    if (!tot) cout << x;
    else cout << ' ' << x;
    tot++;
}

void print_path2(int x, int *p) {
    if (x == -1) return;
    if (!tot) cout << x;
    else cout << ' ' << x;
    tot++;
    print_path2(p[x], p);
}

int main() {
    int kase = 0;
    while (~scan3(n, S, E)) {
        scan(m);
        init();
        for (int i = 0; i < m; i++) {
            int x, y, z;
            scan3(x, y, z);
            addedge(x, y, z);
            addedge(y, x, z);
        }
        scan(k);
        for (int i = 0; i < k; i++) {
            int x, y, z;
            scan3(x, y, z);
            quick.push_back(Edge(x, y, z));
            quick.push_back(Edge(y, x, z));
        }
        int d1[maxn], d2[maxn], p1[maxn], p2[maxn];
        dijkstra(S, d1, p1);
        dijkstra(E, d2, p2);
        int _s = quick.size();
        int f[maxn], res = d1[E], sta = 1, sed = 1;
        for (int i = 0; i < _s; i++) {
            Edge e = quick[i];
            f[i] = quick[i].dist;
            f[i] += d1[quick[i].from];
            f[i] += d2[quick[i].to];
            if (f[i] < res) {
                res = f[i];
                sta = quick[i].from;
                sed = quick[i].to;
            }
        }
        if (kase) pl();
        kase++;
        if (res != d1[E]) {
            print_path(sta, p1);
            print_path2(sed, p2);
            pl();
            printf("%d\n%d\n", sta, res);
        } else {
            print_path(E, p1);
            pl();
            puts("Ticket Not Used");
            printf("%d\n", res);
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值