LeCoz

导航

2015沈阳站-Meeting 最短路

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

题目大意:A,B两个人分别在1和n区。给出区之间有联系的图以及到达所需时间。求两个人见面最短时间以及在哪个区碰面(可有多个)。多个区被当成一个集合(set),集合中的点互相到达时间相同,并且一定能互达。

 

思路:在于边的数量庞大。需要着手解决的问题是如何建图使得边的数目减小。

题目的特殊点在于:每个区域内部的点点距离是相同的。

所以,构造虚拟结点,解决边数过多的问题。 (n*(n-1))/2 ---------> n+1  是一个很明显的优化

然后1n进行两次spfa,第一次spfa进行完,如果1n不联通(因为是无向边)直接输出 Evil John。(不卡spfa😢)

之后进行枚举,选择最小的时间。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <cmath>
  5 #include <cstdio>
  6 #include <vector>
  7 #include <queue>
  8 #include <set>
  9 #include <map>
 10 #include <stack>
 11 #define ll long long
 12 //#define local
 13 
 14 using namespace std;
 15 
 16 const int MOD = 1e9+7;
 17 const long long inf = 0x3f3f3f3f3f;
 18 const int maxedge = 2e6+5;
 19 const int maxnode = 1e6+1e5+5;
 20 struct Edge {
 21     int u, v, w;
 22     int pre;
 23 } edge[maxedge];
 24 ll dist[maxnode];
 25 ll dist1[maxnode];
 26 ll dist2[maxnode];
 27 int inque[maxnode];
 28 int point[maxnode];
 29 int a[1000005];
 30 int n, m, cnt, node;
 31 ll t, tmp;
 32 vector<int> v;
 33 
 34 void AddEdge(int u, int v, int w) {
 35     edge[cnt].u = u;
 36     edge[cnt].v = v;
 37     edge[cnt].w = w;
 38     edge[cnt].pre = point[u];
 39     point[u] = cnt++;
 40 }
 41 
 42 void spfa (int start) {
 43     for (int i = 0; i <= n+m+1; i++) dist[i] = inf;
 44     memset(inque, 0, sizeof(inque));
 45     dist[start] = 0;
 46     queue<int> q;
 47     q.push(start);
 48     while (q.size()) {
 49         int u = q.front();
 50         q.pop();
 51         inque[u] = 0;
 52         for (int i = point[u]; i != -1; i = edge[i].pre) {
 53             int v = edge[i].v;
 54             if(dist[v] > dist[u]+edge[i].w) {
 55                 dist[v] = dist[u]+edge[i].w;
 56                 if(!inque[v]) {
 57                     inque[v] = 1;
 58                     q.push(v);
 59                 }
 60             }
 61         }
 62     }
 63 }
 64 
 65 int main() {
 66 #ifdef local
 67     if(freopen("/Users/Andrew/Desktop/data.txt", "r", stdin) == NULL) printf("can't open this file!\n");
 68 #endif
 69     int T;
 70     int w,s;
 71     int kase = 0;
 72     scanf("%d", &T);
 73     while (T--) {
 74         scanf("%d%d", &n, &m);
 75         cnt = 0;
 76         node = n+1;
 77         memset(point, -1, sizeof(point));
 78         for (int i = 0; i < m; ++i) {
 79             scanf("%d%d", &w, &s);
 80             for (int j = 0; j < s; ++j) {
 81                 scanf("%d", &a[j]);
 82                 AddEdge(a[j], node, w);
 83                 AddEdge(node, a[j], w);
 84             }
 85             node++;
 86         }
 87         printf("Case #%d: ", ++kase);
 88         spfa(1);
 89         if (dist[n] == inf) {
 90             printf("Evil John\n");
 91             continue;
 92         }
 93         for (int i = 1; i <= n; ++i) dist1[i] = dist[i];
 94         spfa(n);
 95         for (int i = 1; i <= n; ++i) dist2[i] = dist[i];
 96         t = inf;
 97         for (int i = 1; i <= n; ++i) {
 98             tmp = max(dist1[i], dist2[i]);
 99             t = min(t, tmp);
100         }
101         v.clear();
102         for (int i = 1; i <= n; ++i) {
103             if (t == max(dist1[i], dist2[i]))
104                 v.push_back(i);
105         }
106         t /= 2;
107         cout<< t <<endl;
108         for (int i = 0; i < v.size(); i++) {
109             if(!i) printf("%d", v[i]);
110             else printf(" %d", v[i]);
111         }
112         printf("\n");
113     }
114 #ifdef local
115     fclose(stdin);
116 #endif
117     return 0;
118 }
View Code

 

posted on 2018-11-21 00:07  LeCoz  阅读(141)  评论(0编辑  收藏  举报