zoukankan      html  css  js  c++  java
  • 学习最短路建图 HUD 5521

    http://acm.hdu.edu.cn/showproblem.php?pid=5521

    题目大意:有n个点,m个集合,每个集合里面的点都两两可达且每条边权值都是val,有两个人A, B,A在pos=1,B在pos=n,问两者相遇的最短时间,输出相遇地点,如果有多个最短时间,输出的相遇地点按从小到大排序。

    思路:因为集合暴力枚举点肯定mle。所以我不会TAT(我好菜啊)。于是看了一下别人的想法, 就是新建一个节点,然后让集合里面的所有节点都连向他, 然后权值定为和原来的权值一样,也是val(但是最后的ans要除以2)。 TAT,既然我都已经刷过网络流了,既然这个都没有想到

    接下来就简单了。。。dijstra跑两次就好了= =

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const LL inf = 1e17;
    const int maxn = 2e6 + 5;
    struct Edge{
        int from, to; LL val;
        Edge(int f = 0, int t = 0, LL val = 0): from(f), to(t), val(val){}
    };
    struct Point{
        int from; LL val;
        Point(int f = 0, LL val = 0): from(f), val(val){}
        bool operator < (const Point &a) const{
            return val > a.val;
        }
    };
    vector<Edge> G[maxn];
    int kase, n, m;
    int a[maxn];
    
    void build(int newpoint, int cnt, LL t){
        for (int i = 1; i <= cnt; i++){
            G[a[i]].push_back(Edge(a[i], newpoint, t));
            G[newpoint].push_back(Edge(newpoint, a[i], t));
        }
    }
    LL d[maxn], d1[maxn], d2[maxn];
    void dijstra(int s){
        for (int i = 1; i <= n + m; i++){
            d[i] = inf;
        }
        d[s] = 0;
        priority_queue<Point> que;
        que.push(Point(s, d[s]));
        while (!que.empty()){
            Point u = que.top(); que.pop();
            int len = G[u.from].size();
            for (int i = 0; i < len; i++){
                Edge p = G[u.from][i];
                int v = p.to;
                if (d[v] > d[u.from] + p.val){
                    d[v] = d[u.from] + p.val;
                    que.push(Point(v, d[v]));
                }
            }
        }
    }
    
    void solve(){
        dijstra(1);
        for (int i = 1; i <= n; i++) d1[i] = d[i];
        dijstra(n);
        for (int i = 1; i <= n; i++) d2[i] = d[i];
        LL minival = inf;
        for (int i = 1; i <= n; i++){
            minival = min(minival, max(d1[i], d2[i]));
        }
        if (minival == inf) {
            printf("Case #%d: Evil John
    ", ++kase);
            return ;
        }
        vector<int> v;
        for (int i = 1; i <= n; i++){
            if (minival == max(d1[i], d2[i])) v.push_back(i);
        }
        printf("Case #%d: %I64d
    ", ++kase, minival / 2);
        for (int i = 0; i < v.size(); i++){
            printf("%d%c", v[i], i == v.size() - 1 ? '
    ' : ' ');
        }
    }
    
    int main(){
        int T; cin >> T;
        while (T--){
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n + m; i++) G[i].clear();
            for (int i = 1; i <= m; i++){
                LL t; int cnt; scanf("%I64d%d", &t, &cnt);
                for (int j = 1; j <= cnt; j++){
                    scanf("%d", a + j);
                }
                build(i + n, cnt, t);
            }
            solve();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    让人难以想出的动态转移方程小集
    初识DP
    CSP复赛day2模拟题
    通知
    未完成作业
    2019年东莞特长生 散步
    营救
    农场主
    安全密码
    开发区规划
  • 原文地址:https://www.cnblogs.com/heimao5027/p/5960234.html
Copyright © 2011-2022 走看看