POJ - 3268:Silver Cow Party

Title description:

input Output:

 Ideas:

After reading the question, I feel that this question is simply a piece of cake, isn't it just two dijkstra, just have hands, (it turns out that I am a waste...)

But as I looked at the question, I saw that f(i) described in the question is the shortest path from x to i + the shortest path from i to x, and finally max f(i) is required

I was stunned. Isn’t a shortest path and a max value conflicting? Isn’t it embarrassing for the person who wrote this question (***)

But after listening to the teacher's explanation, I gradually understood a little bit. Here I will quote an example from the class at that time to explain it to everyone.

Qingdao->Shanghai: Qingdao-Jinan-Shanghai (go, 6 hours); Shanghai-Qingdao (back, 3 hours) a total of 9 hours Qingdao->Yantai: Qingdao-
Yantai (go, 2 hours); Yantai-Qingdao (back, 3 hours) 2 hours) Total 4 hours
Qingdao->Qinghai: Qingdao-Qinghai (go, 6 hours); Qinghai-Qingdao (back, 6 hours) Total 12 hours

Four cities are given, namely Qingdao, Shanghai, Yantai, and Qinghai. Given your city x, let f(i) be the shortest path from city i to city x, plus the shortest path from city x to city i, and find the maximum value of f(i).
Now x is Qingdao. i can be Shanghai, Yantai, Qinghai
f(Shanghai)=9
f(yt)=4
f(qh)=12

max{f} = max(f(sh), f(yt), f(qh)) = 12

//This is simply the gospel of obsessive-compulsive disorder qwq

Presumably seeing this, everyone may have a little insight in their hearts, and I will talk about it in detail;

What is the so-called max value of finding the shortest path? Here is another example for you:

Suppose the x of this question is regarded as 5;

The remaining four points are 1,2,3,4 respectively. Among them, 1->2, 1->3, 3->4, 2->5, 4->5, I will find out 1, 2, 3, 4 by using the graph formed by the information just now Point the shortest path from each point to 5 points, add their sums together, and finally select a max value from the 4 sums completed by the addition.

//It seems that the shortest path and the max value do not conflict. Unfortunately, I wanted to be bald at the time, but ended up using a very clumsy and useless pure relaxation operation to complete this problem.            

 Then there is basically no difficulty in thinking about this question, just use a reverse edge construction to perform dijkstra. There are many little tricks in the code.

#include <cstring>
#include <cmath>
#include <iostream>
#include <queue>
#include <map>
#include <vector>

const int N = 100005;

struct EDGE {
    int v, w, next;
} e[2][N << 1];

int head[2][N], tot[2] = {1, 1};//为啥要建立二维数组呢?是不是很新奇
//因为正反向建边是完全不同的,要两次来记录,用二维数组较为方便,简洁。
void add(int u, int v, int w, int opt) {//因为反向建边说明我们要建两次
    e[opt][tot[opt]].v = v;//opt就是记录我们是正向建边,还是反向建边
    e[opt][tot[opt]].w = w;
    e[opt][tot[opt]].next = head[opt][u];
    head[opt][u] = tot[opt] ++;
}

struct Node {
    int pos, dis;
    
    Node() {};

    Node(int pos, int dis): pos(pos), dis(dis) {};

    bool operator < (const Node &x) const {
        return dis > x.dis;
    }
};

int dis[2][N], vis[N];

void dijkstra(int opt, int s) {
    std::priority_queue<Node> q;
    memset(dis[opt], 0x3f, sizeof dis[opt]);
    memset(vis, 0, sizeof vis);
    dis[opt][s] = 0;
    q.push(Node(s, 0));
    while (!q.empty()) {//比普通的dijkstra就多了一个opt,就多了一个两种方向的建边而已
        Node f = q.top();
        q.pop();
        int u = f.pos;
        if (vis[u]) continue;
        vis[u] = 1;
        for (int i = head[opt][u]; i; i = e[opt][i].next) {
            int v = e[opt][i].v;
            int w = e[opt][i].w;
            if (!vis[v] && dis[opt][v] > dis[opt][u] + w) {
                dis[opt][v] = dis[opt][u] + w;
                q.push(Node(v, dis[opt][v]));
            }
        }
    }
}

int main() {
    // freopen("/Users/chant/in.txt", "r", stdin);
    int n, m, x;
    std::cin >> n >> m >> x;
    for (int i = 0; i < m; i++) {
        int u, v, w;
        std::cin >> u >> v >> w;
        add(u, v, w, 0);
        add(v, u, w, 1);
    }
    dijkstra(0, x);
    dijkstra(1, x);
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        ans = std::max(ans, dis[0][i] + dis[1][i]);
    }
    std::cout << ans << '\n';
    return 0;
}

Summary: The difficulty of this question is the minimum value & max value listed before, as well as the ingenious use of opt for forward and reverse edge building. The optimal solution method is quite strange.

Creation is not easy, please do not prostitute www! Please give the author three consecutive + attention! Thanks!

Guess you like

Origin blog.csdn.net/2301_76331300/article/details/131597942