• HDU5521 Meeting 题解 最短路


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5521

    题目大意:
    (n) 个点 (m) 个集合,一个点可能处于若干个集合内,属于第 (i) 个集合的任意两点间的距离是 (t_i) ,点 (1) 是起点,点 (n) 是终点。
    你现在需要找到所有点中到 (1)(n) 两点的距离的较大值的最小值,并输出所有满足要求的点。

    解题思路:
    这道题目难的不是最短路,而是建图。
    因为最多可能有 (n) 个点在同一个集合,而 (n le 2 imes 10^5) ,所以两两之间建边显然是不可取的,所以我们需要采用另一种方式建图:
    为每一个集合对应一个点,第 (i) 个集合对应点 (n+i) ,然后从 (n+i) 连向所有第 (i) 个集合中的点一条权值为 (t_i) 的有向边,从第 (i) 个集合中的所有点连向点 (n+i) 一条权值为 (0) 的边。然后分别以点 (1) 和点 (n) 为起点求两边最短路。

    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 200020;
    int T, n, m, e, dist1[maxn], dist2[maxn];
    bool inq[maxn];
    struct Node {
        int v, w;
        Node () {};
        Node (int _v, int _w) { v = _v; w = _w; }
    };
    vector<Node> g[maxn];
    queue<int> que;
    vector<int> ans_vec;
    // 一共n+m个点
    void init() {
        for (int i = 1; i <= n+m; i ++) g[i].clear();
    }
    void spfa(int st, int dist[]) {
        memset(dist, -1, sizeof(int)*(1+n+m));
        memset(inq, 0, sizeof(inq));
        while (!que.empty()) que.pop();
        dist[st] = 0;
        que.push(st);
        while (!que.empty()) {
            int u = que.front();
            que.pop();
            inq[u] = false;
            int sz = g[u].size();
            for (int i = 0; i < sz; i ++) {
                int v = g[u][i].v, w = g[u][i].w;
                if (dist[v] == -1 || dist[v] > dist[u] + w) {
                    dist[v] = dist[u] + w;
                    if (!inq[v]) {
                        inq[v] = true;
                        que.push(v);
                    }
                }
            }
        }
    }
    int main() {
        scanf("%d", &T);
        for (int cas = 1; cas <= T; cas ++) {
            scanf("%d%d", &n, &m);
            init();
            for (int i = 1; i <= m; i ++) {
                int t, s, u;
                scanf("%d%d", &t, &s);
                while (s --) {
                    scanf("%d", &u);
                    g[n+i].push_back(Node(u, t));
                    g[u].push_back(Node(n+i, 0));
                }
            }
            spfa(1, dist1);
            spfa(n, dist2);
            int ans = -1;
            for (int i = 1; i <= n; i ++)
                if (dist1[i] != -1 && dist2[i] != -1 && (ans==-1 || ans > max(dist1[i], dist2[i])))
                    ans = max(dist1[i], dist2[i]);
            printf("Case #%d: ", cas);
            if (ans == -1) puts("Evil John");
            else {
                printf("%d
    ", ans);
                ans_vec.clear();
                for (int i = 1; i <= n; i ++) if (dist1[i] != -1 && dist2[i] != -1 && max(dist1[i], dist2[i])==ans)
                    ans_vec.push_back(i);
                int sz = ans_vec.size();
                for (int i = 0; i < sz; i ++) {
                    if (i) putchar(' ');
                    printf("%d", ans_vec[i]);
                }
                puts("");
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    算法总结——二分法(binary-search)
    Codeforces Round #296 (Div. 2)——B——Error Correct System
    Codeforces Round #296 (Div. 2)——A——Playing with Paper
    广工校赛——GCD,LCM——我是好人
    广工校赛——并查集——变形金刚
    广工校赛——DP——悦动达人
    广工校赛——slamdunk正在做菜
    广工校赛——LCS——完美串
    区间DP——石子合并问题
    贪心 Codeforces Round #109 (Div. 2) B. Combination
  • 原文地址:https://www.cnblogs.com/quanjun/p/12003430.html
Copyright © 2020-2023  润新知