• [CODEVS1917] 深海机器人问题(最小费用最大流)


    传送门

    【问题分析】 

    最大费用最大流问题。 

    【建模方法】 

    把网格中每个位置抽象成网络中一个节点,建立附加源S汇T。 

    1、对于每个顶点i,j为i东边或南边相邻的一个节点,连接节点i与节点j一条容量为1,费用为该边价值的有向边。 
    2、对于每个顶点i,j为i东边或南边相邻的一个节点,连接节点i与节点j一条容量为无穷大,费用为0的有向边。 
    3、从S到每个出发点i连接一条容量为该点出发的机器人数量,费用为0的有向边。 
    4、从每个目标点i到T连接一条容量为可以到达该点的机器人数量,费用为0的有向边。 

    求最大费用最大流,最大费用流值就采集到的生物标本的最高总价值。 

    【建模分析】 

    这个问题可以看做是多出发点和目的地的网络运输问题。每条边的价值只能计算一次,容量限制要设为1。同时还将要连接上容量不限,费用为0的重边。由于“多个深海机器人可以在同一时间占据同一位置”,所以不需限制点的流量,直接求费用流即可。

    吐槽:这出题人语文tm谁教的,输入看了我老半天

    只需要知道权值不在点,而到了边上,而起点和终点变成了多个,起点和终点都有容量限制。

    反而使题目变简单了(因为不再有没有权值的边,而且权值在边上比权值在点上多了一个好处——不用拆点)。

    ——代码

      1 #include <queue>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <iostream>
      5 #define INF 1e9
      6 #define N 1000001
      7 #define min(x, y) ((x) < (y) ? (x) : (y))
      8 
      9 int a, b, n, m, cnt, s, t;
     10 int dis[N], pre[N];
     11 int head[N], to[N << 1], val[N << 1], cost[N << 1], next[N << 1];
     12 bool vis[N];
     13 
     14 inline int read()
     15 {
     16     int x = 0, f = 1;
     17     char ch = getchar();
     18     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
     19     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
     20     return x * f;
     21 }
     22 
     23 inline int hash(int x, int y)
     24 {
     25     return x * m + y;
     26 }
     27 
     28 inline void add2(int x, int y, int z, int c)
     29 {
     30     to[cnt] = y;
     31     val[cnt] = z;
     32     cost[cnt] = c;
     33     next[cnt] = head[x];
     34     head[x] = cnt++;
     35 }
     36 
     37 inline void add(int x, int y, int z, int c)
     38 {
     39     add2(x, y, z, c);
     40     add2(y, x, 0, -c);
     41 }
     42 
     43 inline bool spfa()
     44 {
     45     int i, u, v;
     46     std::queue <int> q;
     47     memset(vis, 0, sizeof(vis));
     48     memset(pre, -1, sizeof(pre));
     49     memset(dis, 127 / 3, sizeof(dis));
     50     q.push(s);
     51     dis[s] = 0;
     52     while(!q.empty())
     53     {
     54         u = q.front(), q.pop();
     55         vis[u] = 0;
     56         for(i = head[u]; i ^ -1; i = next[i])
     57         {
     58             v = to[i];
     59             if(val[i] && dis[v] > dis[u] + cost[i])
     60             {
     61                 dis[v] = dis[u] + cost[i];
     62                 pre[v] = i;
     63                 if(!vis[v])
     64                 {
     65                     q.push(v);
     66                     vis[v] = 1;
     67                 }
     68             }
     69         }
     70     }
     71     return pre[t] ^ -1;
     72 }
     73 
     74 inline int dinic()
     75 {
     76     int i, d, sum = 0;
     77     while(spfa())
     78     {
     79         d = INF;
     80         for(i = pre[t]; i ^ -1; i = pre[to[i ^ 1]]) d = min(d, val[i]);
     81         for(i = pre[t]; i ^ -1; i = pre[to[i ^ 1]])
     82         {
     83             val[i] -= d;
     84             val[i ^ 1] += d;
     85         }
     86         sum += dis[t] * d;
     87     }
     88     return sum;
     89 }
     90 
     91 int main()
     92 {
     93     int i, j, k, x, y;
     94     a = read();
     95     b = read();
     96     n = read();
     97     m = read();
     98     n++, m++;
     99     s = 0, t = N - 1;
    100     memset(head, -1, sizeof(head));
    101     for(i = 0; i < n; i++)
    102         for(j = 1; j < m; j++)
    103         {
    104             x = read();
    105             add(hash(i, j), hash(i, j + 1), 1, -x);
    106             add(hash(i, j), hash(i, j + 1), INF, 0);
    107         }
    108     for(j = 1; j <= m; j++)
    109         for(i = 0; i < n - 1; i++)
    110         {
    111             x = read();
    112             add(hash(i, j), hash(i + 1, j), 1, -x);
    113             add(hash(i, j), hash(i + 1, j), INF, 0);
    114         }
    115     while(a--)
    116     {
    117         k = read();
    118         x = read();
    119         y = read();
    120         add(s, hash(x, y + 1), k, 0);
    121     }
    122     while(b--)
    123     {
    124         k = read();
    125         x = read();
    126         y = read();
    127         add(hash(x, y + 1), t, k, 0);
    128     }
    129     printf("%d
    ", -dinic());
    130     return 0;
    131 }
    View Code
  • 相关阅读:
    牛客网-练习题
    牛客网-趋势科技-2020届校园招聘上机考试-1
    976. Largest Perimeter Triangle--Easy
    812. Largest Triangle Area--Easy
    123. Best Time to Buy and Sell Stock III--Hard
    1131. Maximum of Absolute Value Expression--Medium
    1103. Distribute Candies to People--Easy
    满足高并发的I/O Reactor线程模型 (附图,附代码)
    最简洁易懂的方式介绍I/O模型
    从鸿蒙OS的特性看华为应对封锁的策略
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/7009113.html
Copyright © 2020-2023  润新知