zoukankan      html  css  js  c++  java
  • hdu 5521 Meeting(最短路)

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

     


    题意:有1-n共n个点,给出m个块(完全图),并知道块内各点之间互相到达花费时间均为ti。已知两人分别在点1和点n,求在哪些点相遇能使得花费时间最短。


    题解:显然先想到从点1和点n分别求最短路,然后枚举点找出哪些点是相遇花费时间最少的。但是这题边太多了,假设一个完全图里有x个点,那边就有x*(x-1)/2条了,必须化简其边。一个可行的办法是给每个完全图增加两个点,分别为入点和出点,入点向其中的点连边,其中的点再向出点连边,权均为0,出点向入点连边,权为ti,边数就化简为2*x了。

    代码实现:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const ll INF = 1e18;
     5 const int N = 2100010;
     6 const int M = 2100010;
     7 struct edge {
     8     int to;
     9     ll cost;
    10     edge(int _to, ll _cost):to(_to),cost(_cost){}
    11 };
    12 typedef pair<ll, int> P;// first是最短距离,second是顶点的编号
    13 int V;
    14 vector<edge>G[N];
    15 ll d[2][N];//点1 和 点n 到达其他点的最短时间
    16 void dij(int id, int s) {
    17     priority_queue<P, vector<P>, greater<P> > que;
    18     for(int i = 0; i <= V; ++i) d[id][i] = INF;
    19     d[id][s] = 0;
    20     que.push(P(0, s));
    21 
    22     while(!que.empty()) {
    23         P p = que.top(); que.pop();
    24         int v = p.second;
    25         if(d[id][v] < p.first) continue;
    26         int num = G[v].size();
    27         for(int i = 0; i < num; ++i) {
    28             edge e = G[v][i];
    29             if(d[id][e.to] > d[id][v] + e.cost) {
    30                 d[id][e.to] = d[id][v] + e.cost;
    31                 que.push(P(d[id][e.to], e.to));
    32             }
    33         }
    34     }
    35 }
    36 int main() {
    37     int k, T, t, n, m, i, s, x, u, v;
    38     scanf("%d", &T);
    39     for(k = 1; k <= T; ++k) {
    40         for(i = 0; i < N; ++i) G[i].clear();
    41         scanf("%d%d", &n, &m);//点数,集合(完全图)数目
    42         for(i = 1; i <= 2*m; i += 2) {
    43             u = n+i;//入点
    44             v = n+i+1;//出点
    45             scanf("%d%d", &t, &s);//时间,集合中点数
    46             while(s--) {
    47                 scanf("%d", &x);
    48                 G[u].push_back(edge(x, 0));
    49                 G[x].push_back(edge(v, 0));
    50             }
    51             G[v].push_back(edge(u, t));
    52         }
    53         V = n+2*m;
    54         dij(0, 1);
    55         dij(1, n);
    56         /*
    57         puts("-----------------");
    58         for(i = 1; i <= n; ++i) {
    59             printf("%lld, %lld
    ", d[0][i], d[1][i]);
    60         }
    61         puts("-----------------");
    62         */
    63         ll mi = INF;
    64         int cnt = 0;
    65         ll a = 0;
    66         for(i = 1; i <= n; ++i) {
    67             if((a = max(d[0][i], d[1][i])) < mi) {
    68                 mi = a;
    69             }
    70         }
    71         printf("Case #%d: ", k);
    72         if(mi == INF) {
    73             printf("Evil John
    ");
    74         }
    75         else {
    76             int f = 0;
    77             printf("%lld
    ", mi);
    78             for(i = 1; i <= n; ++i) {
    79                 a = max(d[0][i], d[1][i]);
    80                 if(a == mi) {
    81                     if(f) putchar(' ');
    82                     printf("%d", i);
    83                     f = 1;
    84                 }
    85             }
    86             puts("");
    87         }
    88     }
    89     return 0;
    90 }
    2667ms
  • 相关阅读:
    LeetCode 24. Swap Nodes in Pairs (两两交换链表中的节点)
    LeetCode 1041. Robot Bounded In Circle (困于环中的机器人)
    LeetCode 1037. Valid Boomerang (有效的回旋镖)
    LeetCode 1108. Defanging an IP Address (IP 地址无效化)
    LeetCode 704. Binary Search (二分查找)
    LeetCode 744. Find Smallest Letter Greater Than Target (寻找比目标字母大的最小字母)
    LeetCode 852. Peak Index in a Mountain Array (山脉数组的峰顶索引)
    LeetCode 817. Linked List Components (链表组件)
    LeetCode 1019. Next Greater Node In Linked List (链表中的下一个更大节点)
    29. Divide Two Integers
  • 原文地址:https://www.cnblogs.com/GraceSkyer/p/8723943.html
Copyright © 2011-2022 走看看