BuringStraw

BuringStraw

P3106 GPS的决斗

题目#

(翻译太水了所以用英文)

Farmer John 最近在线购买了一辆新车,但由于匆忙,他在选择额外功能时不小心点击了 “提交” 按钮两次,结果这辆车配备了两个 GPS 导航系统!更糟糕的是,这两个系统经常对 FJ 应该选择的路线做出相互冲突的决定。

FJ 所在地区的地图由 N 个交叉口 (2 <= N <= 10,000) 和 M 条单向道路 (1 <= M <= 50,000) 组成。道路 i 连接交叉口 A_i (1 <= A_i <= N) 和 B_i (1 <= B_i <= N)。多条道路可以连接同一对交叉口,双向道路 (允许双向通行) 由两个方向相反的单向道路表示。FJ 的家位于交叉口 1,他的农场位于交叉口 N。可以通过沿着一系列单向道路从他的家到达农场。

两个 GPS 单元使用的底层地图如上所述;然而,它们对每条道路的行驶时间有不同的看法。根据第一个 GPS 单元,道路 i 需要 P_i 单位时间通过,而根据第二个单元则需要 Q_i 单位时间通过 (每个行驶时间都是 1..100,000 范围内的整数)

FJ 想要从他的家前往农场。然而,每当 FJ 跟随一条道路 (比如,从交叉口 X 到交叉口 Y) 时,GPS 单元都会大声抱怨,认为这条道路不是从 X 到农场的最短路线的一部分 (如果 FJ 走了一条两个 GPS 单元都不喜欢的道路,可能会导致两个 GPS 单元同时抱怨)

请帮助 FJ 确定如果他选择合适的路线,能够收到的最少投诉总数。如果两个 GPS 单元在 FJ 跟随一条道路时都抱怨,这将计为 +2。

输入格式:

  • 第 1 行:整数 N 和 M。

第 i 行描述道路 i,包含四个整数:A_i B_i P_i Q_i。

输出格式:

  • 第 1 行:如果 FJ 从他的家到农场的路线最优,他能够收到的最少投诉总数。

思路#

分别为 gps1 和 gps2 建两个反图,这样就可以 spfa 求出每个点到 n 的最短路和每个点的最短路上的下一条边。然后为 FJ 建一个图,每条边的初始权值为 2,表示警告次数,在求最短路时如果下一条边与某个 GPS 相同,警告次数就减一。

Code#

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;

const int MAXN = 10000 + 5;

int n, m;

struct mp {
    struct ed {
        int to, w, nex;
    } e[MAXN * 6];
    int newp;
    int head[MAXN], fa[MAXN], d[MAXN];
    bool inq[MAXN];

    void lineAdd (int p1, int p2, int w) {
        ++newp;
        e[newp].to = p2;
        e[newp].w = w;
        e[newp].nex = head[p1];
        head[p1] = newp;
    }

    void spfa (int s) {
        memset(inq, 0, sizeof(inq));
        memset(d, 0x3f, sizeof(d));
        queue<int> q;
        q.push(s);
        d[s] = 0;
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            inq[u] = 0;
            for (int i = head[u]; i; i = e[i].nex) {
                int y = e[i].to;
                if (d[u] + (e[i].w) < d[y]) {
                    d[y] = d[u] + e[i].w;
                    fa[y] = i;
                    if (!inq[y]) {
                        q.push(y);
                        inq[y] = 1;
                    }
                }
            }
        }
    }
};

mp g1, g2, fj;

void spfa_for_fj(void) {
    memset(fj.inq, 0, sizeof(fj.inq));
    memset(fj.d, 0x3f, sizeof(fj.d));
    queue<int> q;
    q.push(1);
    fj.d[1] = 0;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        fj.inq[u] = 0;
        for (int i = fj.head[u]; i; i = fj.e[i].nex) {
            int y = fj.e[i].to, w = fj.e[i].w;
            if (g1.fa[u] == i) --w;
            if (g2.fa[u] == i) --w;
            if (fj.d[u] + w < fj.d[y]) {
                fj.d[y] = fj.d[u] + w;
                if (!fj.inq[y]) {
                    q.push(y);
                    fj.inq[y] = 1;
                }
            }
        }
    }
}


int main (void) {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; ++i) {
        int p1, p2, w1, w2;
        scanf("%d%d%d%d", &p1, &p2, &w1, &w2);
        g1.lineAdd(p2, p1, w1);
        g2.lineAdd(p2, p1, w2);
        fj.lineAdd(p1, p2, 2);
    }
    g1.spfa(n);
    g2.spfa(n);
    spfa_for_fj();

    printf("%d\n", fj.d[n]);

    fclose(stdin);
    fclose(stdout);
    return 0;
}

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。