• 【HDU5521】Meeting


    题目大意:给定一张(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;
    }
    
  • 相关阅读:
    pandas isin 和not in
    游戏开发需要学什么?
    打开页面,数字会自增的效果怎么弄?
    jq 导航栏点击添加/删除类(a标签跳转页面)
    bootstrap+jq分页
    2020/12/18
    2020/12/17
    2020/12/16
    2020/12/15
    2020/12/14
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/11784909.html
Copyright © 2020-2023  润新知