【HDU5521】Meeting

題目大意:給定一張\(N\)個點的圖,構成了\(M\)個團,每一個團內的邊權均相等,求圖上有多少個點知足到\(1\)號節點和\(N\)號節點的最大值最小。node

題解:
本題的核心是如何優化連邊,考慮對於每個團增長一個虛擬節點,並讓每一個節點到虛擬節點連一條邊權爲\(t_i\)的有向邊,虛擬節點到團中每個點連一條邊權爲\(0\)的有向邊,最後跑最短路求解便可。ios

注意:數據中有\(0\)下標的節點,讀入時須要忽略,別問我怎麼知道的。。。c++

代碼以下優化

#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;
}
相關文章
相關標籤/搜索