• [bzoj3993][SDOI2015]星际战争-二分+最大流


    Brief Description

    3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战。在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进攻X军团的阵地,其中第i个巨型机器人的装甲值为Ai。当一个巨型机器人的装甲值减少到0或者以下时,这个巨型机器人就被摧毁了。X军团有M个激光武器,其中第i个激光武器每秒可以削减一个巨型机器人Bi的装甲值。激光武器的攻击是连续的。这种激光武器非常奇怪,一个激光武器只能攻击一些特定的敌人。Y军团看到自己的巨型机器人被X军团一个一个消灭,他们急需下达更多的指令。为了这个目标,Y军团需要知道X军团最少需要用多长时间才能将Y军团的所有巨型机器人摧毁。但是他们不会计算这个问题,因此向你求助。

    Algorithm Design

    明明是非常水的套路题却卡了很久, 看来是太长时间没有做网络流的题目手生了, 我真的是思博啊, 我这样的人就应该早点滚粗吧Orz
    我们考虑直接二分答案, 这样所有武器能输出的最大火力就有了, 按照火力建模, 随便搞搞就有了.
    我真是思博啊.
    数组开小了...然后不爽一下子开150万就过了Orz

    Code

    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <queue>
    const double eps = 1e-9;
    #define ld long double
    const int maxn = 110 << 1;
    const int inf = 0x3f3f3f;
    struct edge {
      int to, next;
      ld cap;
      edge(int a = 0, int b = 0, ld c = 0) : to(a), next(b), cap(c) {}
    } e[1500005];
    int cnt = 1, n, m, s, t, v;
    ld L, R;
    int head[maxn], mi[maxn], A[maxn], B[maxn], tod;
    ld dist[maxn];
    void add_edge(int u, int v, ld c) {
      e[++cnt] = edge(v, head[u], c);
      head[u] = cnt;
    }
    void add(int u, int v, ld c) {
      add_edge(u, v, c);
      add_edge(v, u, 0);
    }
    void bfs(int s) {
      std::fill(dist, dist + v, -1);
      dist[s] = 0;
      std::queue<int> q;
      q.push(s);
      while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int i = head[u]; i; i = e[i].next) {
          if (dist[e[i].to] == -1 && e[i].cap > eps) {
            dist[e[i].to] = dist[u] + e[i].cap;
            q.push(e[i].to);
          }
        }
      }
    }
    ld dfs(int s, int t, ld flow) {
      if (s == t)
        return flow;
      for (int i = head[s]; i; i = e[i].next) {
        // printf("%.2f ", e[i].cap);
        if (e[i].cap > eps && dist[e[i].to] > dist[s]) {
          ld d = dfs(e[i].to, t, std::min(e[i].cap, flow));
          if (d > eps) {
            e[i].cap -= d;
            e[i ^ 1].cap += d;
            return d;
          }
        }
      }
      return 0;
    }
    ld dinic(int s, int t) {
      ld flow = 0;
      while (1) {
        bfs(s);
        if (dist[t] == -1)
          return flow;
        ld d;
        while ((d = dfs(s, t, inf)))
          flow += d;
      }
      return flow;
    }
    bool check(ld mid) {
      for (int i = 2; i <= cnt; i += 2)
        e[i].cap += e[i ^ 1].cap, e[i ^ 1].cap = 0;
      for (int i = head[s]; i; i = e[i].next)
        e[i].cap = mid * B[e[i].to];
      ld flow = dinic(s, t);
      return std::fabs(flow - (ld)tod) <= eps;
    }
    int main() {
    #ifndef ONLINE_JUDGE
      freopen("input", "r", stdin);
    #endif
      scanf("%d %d", &n, &m);
      s = 0, t = n + m + 1, v = t + 1, L = 0, R = 0;
      for (int i = 1; i <= n; i++) {
        scanf("%d", &A[i]);
        mi[i] = inf;
      }
      for (int i = 1; i <= m; i++)
        scanf("%d", &B[i]);
      for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
          int x;
          scanf("%d", &x);
          if (x == 1) {
            add(i, j + m, inf);
            mi[j] = std::min(mi[j], B[i]);
          }
        }
        add(0, i, inf);
      }
      for (int i = 1; i <= n; i++) {
        R += A[i] / mi[i];
        add(i + m, t, A[i]);
        tod += A[i];
      }
      //  printf("%d
    ", tod);
      R = 5e6;
      while (R - L > eps) {
        ld mid = (L + R) / 2;
        if (check(mid))
          R = mid;
        else
          L = mid;
      }
      printf("%.7Lf", (L + R) / 2);
    }
    
  • 相关阅读:
    怎么把自己电脑上的文件传到服务器本地上
    查看hive中某个表中的数据、表结构及所在路径
    python2.7读汉字的时候出现乱码,如何解决
    如何连接服务器客户端
    java常用问题排查工具
    netty源码分析之一:server的启动
    java AQS 一:
    netty源码分析之二:accept请求
    java Resource
    二:基础概述netty
  • 原文地址:https://www.cnblogs.com/gengchen/p/6596826.html
Copyright © 2020-2023  润新知