zoukankan      html  css  js  c++  java
  • HDU 5521 Meeting 最短路

    题意:

    (n)个点和(m)个点的集合(E_i),每个集合中的点两两相邻而且通过任意两点之间需要的时间为(t_i)
    有两个人分别从(1)(n)出发,确定一个相遇点使得两个人相遇的时间最短。

    参考博客

    分析:

    起初想法是跑两遍最短路,分别计算(1)(n)为起点时的最短路(ds(i))(dt(i))
    那么所求的最短时间为(min\{ max(ds(i), dt(i)) \})

    但是边的数量太多了,传统的建图方法行不通。
    考虑题目所给的条件,在途中新增(m)个点代表这些集合。
    对于一个点(u)和它所属的集合(S),建一条(u ightarrow S)权值为(0)的边,和一条(S ightarrow u)的权值为(w)的边。
    然后求最短路就是答案。

    说一下我对这种见图方法的理解:

    • (u ightarrow S)表示从点(u)进入集合,因为点本来就在集合中所以不需要花费。
    • (S ightarrow u)表示在集合中从一个点移动到另一个点,花费为(w)
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <vector>
    #define MP make_pair
    using namespace std;
    
    typedef pair<int, int> PII;
    const int maxn = 200000 + 10;
    const int INF = 0x3f3f3f3f;
    
    struct Edge
    {
        int u, v, d;
        Edge() {}
        Edge(int u, int v, int d):u(u), v(v), d(d) {}
    };
    
    int n, m;
    vector<int> G[maxn];
    vector<Edge> edges;
    
    void init(int n) {
        for(int i = 1; i <= n; i++) G[i].clear();
        edges.clear();
    }
    
    void AddEdge(int u, int v, int d) {
        edges.push_back(Edge(u, v, d));
        edges.push_back(Edge(v, u, 0));
        int m = edges.size();
        G[u].push_back(m - 2);
        G[v].push_back(m - 1);
    }
    
    int ds[maxn], dt[maxn];
    bool vis[maxn];
    
    void Dijkstra(int* d, int s) {
        memset(d, 0x3f, sizeof(ds));
        memset(vis, false, sizeof(vis));
        d[s] = 0;
        priority_queue<PII, vector<PII>, greater<PII> > Q;
        Q.push(MP(0, s));
    
        while(!Q.empty()) {
            PII x = Q.top(); Q.pop();
            int u = x.second;
            if(vis[u]) continue;
            vis[u] = true;
            for(int i = 0; i < G[u].size(); i++) {
                Edge& e = edges[G[u][i]];
                int v = e.v;
                if(d[u] + e.d < d[v]) {
                    d[v] = d[u] + e.d;
                    Q.push(MP(d[v], v));
                }
            }
        }
    }
    
    int main()
    {
        int T; scanf("%d", &T);
        for(int kase = 1; kase <= T; kase++) {
            scanf("%d%d", &n, &m);
            init(n + m);
            for(int i = 1; i <= m; i++) {
                int d, cnt; scanf("%d%d", &d, &cnt);
                while(cnt--) {
                    int u; scanf("%d", &u);
                    AddEdge(n + i, u, d);
                }
            }
    
            printf("Case #%d: ", kase);
    
            Dijkstra(ds, 1);
            if(ds[n] == INF) { printf("Evil John
    "); continue; }
            Dijkstra(dt, n);
    
            #ifdef DEBUG
            printf("ds: ");
            for(int i = 1; i <= n; i++) printf("%d ", ds[i]);
            printf("
    dt: ");
            for(int i = 1; i <= n; i++) printf("%d ", dt[i]);
            printf("
    ");
            #endif
    
            int ans = INF;
            for(int i = 1; i <= n; i++) ans = min(ans, max(ds[i], dt[i]));
            printf("%d
    ", ans);
    
            bool flag = false;
            for(int i = 1; i <= n; i++) {
                if(max(ds[i], dt[i]) == ans) {
                    if(flag) printf(" ");
                    printf("%d", i); flag = true;
                }
            }
            printf("
    ");
        }
    
        return 0;
    }
    
  • 相关阅读:
    CentOS8下安装mysql8
    Git使用
    《操作系统导论》读书笔记
    《Linux命令行大全》读书笔记
    Centos8 开机后显示 Activate the web console with: systemctl enable --now cockpit.socke
    numpy学习笔记
    CentOS8使用阿里源
    Python 面向对象
    matplotlib解决不显示中文问题
    MySQL基础第三课
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4936160.html
Copyright © 2011-2022 走看看