• HDU 5521 Meeting (最短路)


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

    题意:

            有一个n个点的图,会给你m个集合,每个集合内的点,距离都是t[i]

            然后A在点1,B在点n,然后让你找到一个点,使得max(disA[i],disB[i])最小

            如果有多个答案,按照字典序输出所有答案

            如果没有答案输出Evil John

    思路:

            两次dijkstra,注意不能直接建边。对于当前点所在的集合,要是之前没有遍历过,就遍历集合内所有的点,更新d[i]。

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <queue>
      5 #include <map>
      6 using namespace std;
      7 typedef __int64 LL;
      8 typedef pair <LL, int> P;
      9 const int N = 1e5 + 5;
     10 LL d1[N], d2[N], inf = 1e16;
     11 int a[N];
     12 vector <int> G[N], belong[N];
     13 bool vis[N];
     14 void dij(int s, int n) {
     15     for(int i = 1; i <= n; ++i) {
     16         d1[i] = inf;
     17         vis[i] = false;
     18     }
     19     d1[s] = 0;
     20     priority_queue <P, vector<P>, greater<P> > que;
     21     while(!que.empty()) {
     22         que.pop();
     23     }
     24     que.push(make_pair(d1[s], s));
     25     while(!que.empty()) {
     26         P temp = que.top();
     27         int u = temp.second;
     28         que.pop();
     29         if(d1[u] < temp.first)
     30             continue;
     31         for(int i = 0; i < belong[u].size(); ++i) {
     32             int x = belong[u][i];
     33             if(vis[x]) //集合之前遍历过
     34                 continue;
     35             vis[x] = true;
     36             for(int j = 0; j < G[x].size(); ++j) {
     37                 int v = G[x][j];
     38                 if(v != u && d1[v] > d1[u] + a[x]) {
     39                     d1[v] = d1[u] + a[x];
     40                     que.push(make_pair(d1[v], v));
     41                 }
     42             }
     43         }
     44     }
     45 }
     46 void dij2(int s, int n) {
     47     for(int i = 1; i <= n; ++i) {
     48         d2[i] = inf;
     49         vis[i] = false;
     50     }
     51     d2[s] = 0;
     52     priority_queue <P, vector<P>, greater<P> > que;
     53     while(!que.empty()) {
     54         que.pop();
     55     }
     56     que.push(make_pair(d2[s], s));
     57     while(!que.empty()) {
     58         P temp = que.top();
     59         int u = temp.second;
     60         que.pop();
     61         if(d2[u] < temp.first)
     62             continue;
     63         for(int i = 0; i < belong[u].size(); ++i) {
     64             int x = belong[u][i];
     65             if(vis[x]) //集合之前遍历过
     66                 continue;
     67             vis[x] = true;
     68             for(int j = 0; j < G[x].size(); ++j) {
     69                 int v = G[x][j];
     70                 if(v != u && d2[v] > d2[u] + a[x]) {
     71                     d2[v] = d2[u] + a[x];
     72                     que.push(make_pair(d2[v], v));
     73                 }
     74             }
     75         }
     76     }
     77 }
     78 void init(int n) {
     79     for(int i = 1; i <= n; ++i) {
     80         G[i].clear();
     81         belong[i].clear();
     82     }
     83 }
     84 vector <int> res;
     85 int main()
     86 {
     87     int t, n, m;
     88     scanf("%d", &t);
     89     for(int ca = 1; ca <= t; ++ca) {
     90         scanf("%d %d", &n, &m);
     91         init(n);
     92         res.clear();
     93         int num, x;
     94         for(int k = 1; k <= m; ++k) {
     95             scanf("%d %d", &a[k], &num);
     96             for(int i = 1; i <= num; ++i) {
     97                 scanf("%d", &x);
     98                 G[k].push_back(x); //集合k内的点
     99                 belong[x].push_back(k); //点x所在的集合
    100             }
    101         }
    102         dij(1, n);
    103         dij2(n, n);
    104         LL ans = inf;
    105         for(int i = 1; i <= n; ++i) {
    106             ans = min(ans, max(d1[i], d2[i]));
    107         }
    108         printf("Case #%d: ", ca);
    109         if(ans == inf) {
    110             printf("Evil John
    ");
    111         } else {
    112             for(int i = 1; i <= n; ++i) {
    113                 if(d1[i] <= ans && d2[i] <= ans) {
    114                     res.push_back(i);
    115                 }
    116             }
    117             int xx = res.size();
    118             printf("%I64d
    ", ans);
    119             for(int i = 0; i < xx - 1; ++i) {
    120                 printf("%d ", res[i]);
    121             }
    122             printf("%d
    ", res[xx - 1]);
    123         }
    124     }
    125     return 0;
    126 }
  • 相关阅读:
    Python3全栈学习目录
    五句话搞定javavscript作用域
    Python线程池
    luogu4016 负载平衡问题
    luogu2756 飞行员配对方案问题
    luogu1251 餐巾计划问题
    luogu3386 【模板】二分图匹配 匈牙利算法 hdu2063 过山车 dinic
    luogu3381 【模板】最小费用最大流
    luogu3376 【模板】网络最大流 dinic
    luogu2740 [USACO4.2]草地排水Drainage Ditches 最大流EK
  • 原文地址:https://www.cnblogs.com/Recoder/p/5962272.html
Copyright © 2020-2023  润新知