zoukankan      html  css  js  c++  java
  • 【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;
    }
    
  • 相关阅读:
    [js]vue-router的使用
    [js]递归实现 数组转树形
    [js]vue组件核心
    [js]了解chart绘图
    [js]vue权限控制
    [js]vue显示一个外部链接的组件
    [js]axios使用
    [js]vue中 给router-view 组件的 绑定 key 的原因
    [java]BeanPostProcessor使用及源码
    [java]权限管理
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/11784909.html
Copyright © 2011-2022 走看看