"Inspur Cup" Shandong 7th ACM Proxy

topic

Insert picture description here

Title

This question is a bit convoluted (my English reading ability is too poor QAQ).

  1. When there are multiple shortest paths, output several nodes with the smallest sequence number connected to 0 on the shortest paths;
  2. Unreachable, output -1;
  3. Can reach the target node directly and the path is the shortest path, output 0.

answer

Since it is necessary to output the node with the smallest sequence number connected to 0 on the shortest path, it is definitely more troublesome to directly, so we reverse the map, so that the final judgment will be much easier.
Then directly SPFA.
Then judge whether to output the smallest serial number or 0.

AC code (comments are more informative)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>

using namespace std;
//#pragma GCC optimize(2)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ull unsigned long long
#define ll long long
#define rep(i, x, y) for(int i=x;i<=y;i++)
#define mms(x, n) memset(x, n, sizeof(x))
#define mmc(A, tree) memcpy(A, tree, sizeof(tree))
#define eps (1e-8)
#define PI (acos(-1.0))
#define INF (0x3f3f3f3f)
#define mod (ull)(1e9+7)
typedef pair<int, int> P;
const int N = 1e5;

// 前式链向星存图
struct Node {
    int to, w, ne;
} e[N];
int head[N], cnt = 1;
int dist[N];
bool vis[N];
int n, m;
queue<P> q; // 记录与0相连的节点

void init() {
    cnt = 1;
    mms(head, 0);
    fill(dist, dist + N, INF);
    mms(vis, false);
    while (!q.empty()) q.pop();
}

void add(int u, int v, int w) {
    e[cnt].w = w;
    e[cnt].to = v;
    e[cnt].ne = head[u];
    head[u] = cnt++;
}

// 我只是一个普通的SPFA
void SPFA(int s) {
    dist[s] = 0;
    queue<int> q;
    q.push(s);
    vis[s] = true;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        vis[u] = false;
        for (int i = head[u]; i; i = e[i].ne) {
            int v = e[i].to, w = e[i].w;
            if (dist[v] > dist[u] + w) {
                dist[v] = dist[u] + w;
                if (!vis[v]) {
                    q.push(v);
                    vis[v] = true;
                }
            }
        }
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
#endif
    int T;
    scanf("%d", &T);
    while (T--) {
        init();
        scanf("%d%d", &n, &m);
        rep(i, 1, m) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            add(v, u, w);
            if (u == 0) q.push(P(v, w));
        }
        SPFA(n + 1);

        // 重点部分
        if (dist[0] == INF) printf("-1\n"); // 无法到达的情况
        else {
            int ans = INF;
            while (!q.empty()) {
                P p = q.front();
                q.pop();
                int u = p.first, w = p.second;
                if (dist[0] == (dist[u] + w)) { // 取出所有到0的距离与SPFA所得的最短距离相等的节点中序号最小的节点
                    ans = min(u, ans);
                }
            }
            if (ans == n+1) printf("0\n"); // 如果该节点为n+1则说明直达且最短
            else printf("%d\n", ans);
        }
    }
    return 0;
}

postscript

This question really taught me.
I used to copy and paste Google Translate to do the questions in one go. When I really played the game, I could only read the questions by myself. In many places, I had to read the QAQ several times.
Read it by yourself later!

Guess you like

Origin blog.csdn.net/qq_45934120/article/details/108477400