zoukankan      html  css  js  c++  java
  • P3106 GPS的决斗Dueling GPS's


    同步:https://buringstraw.win/index.php/archives/43/

    题目

    Farmer John has recently purchased a new car online, but in his haste he accidentally clicked the "Submit" button twice when selecting extra features for the car, and as a result the car ended up equipped with two GPS navigation systems! Even worse, the two systems often make conflicting decisions about the route that FJ should take.

    The map of the region in which FJ lives consists of N intersections (2 <= N <= 10,000) and M directional roads (1 <= M <= 50,000). Road i connects intersections A_i (1 <= A_i <= N) and B_i (1 <= B_i <= N). Multiple roads could connect the same pair of intersections, and a bi-directional road (one permitting two-way travel) is represented by two separate directional roads in opposite orientations. FJ's house is located at intersection 1, and his farm is located at intersection N. It is possible to reach the farm from his house by traveling along a series of directional roads.

    Both GPS units are using the same underlying map as described above; however, they have different notions for the travel time along each road. Road i takes P_i units of time to traverse according to the first GPS unit, and Q_i units of time to traverse according to the second unit (each travel time is an integer in the range 1..100,000).

    FJ wants to travel from his house to the farm. However, each GPS unit complains loudly any time FJ follows a road (say, from intersection X to intersection Y) that the GPS unit believes not to be part of a shortest route from X to the farm (it is even possible that both GPS units can complain, if FJ takes a road that neither unit likes).

    Please help FJ determine the minimum possible number of total complaints he can receive if he chooses his route appropriately. If both GPS units complain when FJ follows a road, this counts as +2 towards the total.

    思路

    分别为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
    ", fj.d[n]);
    
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    
    
  • 相关阅读:
    【Ubuntu使用技巧】在Ubuntu下制作ISO镜像的方法
    【Linux调试技术1】初步基础
    【算法研究与实现】最小二乘法直线拟合
    【嵌入式学习】移植konquerorembed
    【Asterisk应用】利用Asterisk产生呼叫的脚本
    【LDAP学习】OpenLDAP学习笔记
    一个.NET通用JSON解析/构建类的实现(c#)
    .net泛型在序列化、反序列化JSON数据中的应用
    C#字符串数组排序
    c#中的Json的序列化和反序列化
  • 原文地址:https://www.cnblogs.com/buringstraw/p/11078604.html
Copyright © 2011-2022 走看看