HDU5521Meeting

Posted wzj-xhjbk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU5521Meeting相关的知识,希望对你有一定的参考价值。

题目大意:给定一张(N)个点的图,构成了(M)个团,每个团内的边权均相等,求图上有多少个点满足到(1)号节点和(N)号节点的最大值最小。

题解:
本题的核心是如何优化连边,考虑对于每一个团增加一个虚拟节点,并让每个节点到虚拟节点连一条边权为(t_i)的有向边,虚拟节点到团中每一个点连一条边权为(0)的有向边,最后跑最短路求解即可。

注意:数据中有(0)下标的节点,读入时需要忽略,别问我怎么知道的。。。

代码如下

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

struct node {
  int to;
  LL w;
  node(int _to = 0, LL _w = 0) {
    to = _to;
    w = _w;
  }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0), cout.tie(0);
  int T, kase = 0;
  cin >> T;
  while (T--) {
    int n, m;
    cin >> n >> m;
    vector<vector<node>> adj(n + m);
    for (int i = 0; i < m; i++) {
      LL w;
      int cnt;
      cin >> w >> cnt;
      while (cnt--) {
        int x;
        cin >> x;
        if (x == 0) continue;
        x--;
        adj[i + n].emplace_back(x, 0);
        adj[x].emplace_back(i + n, w);
      }
    }
    auto dij = [&](int st) {
      vector<int> expand(n + m, 0);
      vector<LL> d(n + m, 1e18);
      priority_queue<pair<LL, int>> q;
      d[st] = 0, q.push(make_pair(0, st));
      while (!q.empty()) {
        int x = q.top().second;
        q.pop();
        if (expand[x]) continue;
        expand[x] = 1;
        for (auto e : adj[x]) {
          int y = e.to, w = e.w;
          if (d[y] > d[x] + w) {
            d[y] = d[x] + w;
            q.push(make_pair(-d[y], y));
          }
        }
      }
      return d;
    };
    vector<LL> dst = dij(0);
    vector<LL> ded = dij(n - 1);
    if (dst[n - 1] == 1e18) {
      cout << "Case #" << ++kase << ": Evil John" << endl;
    } else {
      LL ans = 1e17;
      vector<int> p;
      for (int i = 0; i < n; i++) {
        LL ret = max(dst[i], ded[i]);
        if (ret < ans) {
          ans = ret;
          p.clear();
          p.push_back(i + 1);
        } else if (ret == ans) {
          p.push_back(i + 1);
        }
      }
      cout << "Case #" << ++kase << ": " << ans << endl;
      cout << p[0];
      for (int i = 1; i < (int)p.size(); i++) {
        cout << " " << p[i];
      }
      cout << endl;
    }
  }
  return 0;
}

以上是关于HDU5521Meeting的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5521.Meeting 最短路模板题

HDU 5521 Meeting(虚拟节点+最短路)

hdu 5521 Meeting(最短路)

HDU 5521 Meeting 最短路

HDU - 5521 Meeting

Meeting HDU - 5521