zoukankan      html  css  js  c++  java
  • 洛谷P3980 志愿者招募

    题意:懒得写了......

    解:

    一开始想的是每天建点,每种人建点,然后连边费用流,发现一个人可以管辖多天,不好处理。

    回想起了网络流24题中的"最长k可重线段集","最长k可重区间集"等问题,然后发现这题也可以横着流啊。

    具体来说,首先在下面开一条安全快速绿色通道,存放那些不用的人(流量)。

    那么每天要用怎么办?把人逼出去!

    流量设为INF - ai就可以逼出去ai个人了!

    然后每种人都对应一段区间,连边跑最小费用最大流即可。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <queue>
     4 #include <cstring>
     5 
     6 const int N = 1010, M = 1000010, INF = 0x3f3f3f3f;
     7 
     8 struct Edge {
     9     int nex, v, c, len;
    10 }edge[M << 1]; int top = 1;
    11 
    12 int e[N], d[N], vis[N], pre[N], flow[N];
    13 std::queue<int> Q;
    14 
    15 inline void add(int x, int y, int z, int w) {
    16     top++;
    17     edge[top].v = y;
    18     edge[top].c = z;
    19     edge[top].len = w;
    20     edge[top].nex = e[x];
    21     e[x] = top;
    22 
    23     top++;
    24     edge[top].v = x;
    25     edge[top].c = 0;
    26     edge[top].len = -w;
    27     edge[top].nex = e[y];
    28     e[y] = top;
    29     return;
    30 }
    31 
    32 inline bool SPFA(int s, int t) {
    33     memset(d, 0x3f, sizeof(d));
    34     d[s] = 0;
    35     flow[s] = INF;
    36     vis[s] = 1;
    37     Q.push(s);
    38     while(!Q.empty()) {
    39         int x = Q.front();
    40         Q.pop();
    41         vis[x] = 0;
    42         for(int i = e[x]; i; i = edge[i].nex) {
    43             int y = edge[i].v;
    44             if(edge[i].c && d[y] > d[x] + edge[i].len) {
    45                 d[y] = d[x] + edge[i].len;
    46                 pre[y] = i;
    47                 flow[y] = std::min(flow[x], edge[i].c);
    48                 if(!vis[y]) {
    49                     vis[y] = 1;
    50                     Q.push(y);
    51                 }
    52             }
    53         }
    54     }
    55     return d[t] < INF;
    56 }
    57 
    58 inline void update(int s, int t) {
    59     int temp = flow[t];
    60     while(t != s) {
    61         int i = pre[t];
    62         edge[i].c -= temp;
    63         edge[i ^ 1].c += temp;
    64         t = edge[i ^ 1].v;
    65     }
    66     return;
    67 }
    68 
    69 inline int solve(int s, int t, int &cost) {
    70     int ans = 0;
    71     cost = 0;
    72     while(SPFA(s, t)) {
    73         ans += flow[t];
    74         cost += flow[t] * d[t];
    75         update(s, t);
    76     }
    77     return ans;
    78 }
    79 
    80 int main() {
    81     int n, m;
    82     scanf("%d%d", &n, &m);
    83     for(int i = 1, x; i <= n; i++) {
    84         scanf("%d", &x);
    85         add(i, i + 1, INF - x, 0);
    86     }
    87     for(int i = 1, x, y, z; i <= m; i++) {
    88         scanf("%d%d%d", &x, &y, &z);
    89         add(x, y + 1, INF, z);
    90     }
    91     int s = n + 2;
    92     add(s, 1, INF, 0);
    93     int ans;
    94     solve(s, n + 1, ans);
    95     printf("%d", ans);
    96     return 0;
    97 }
    AC代码

    题外话:A了之后我自以为建图很奇葩,跑去看题解,发现都是这种解法......

    还可以用线性规划做...好神奇啊。

  • 相关阅读:
    史上最强验证
    Yii2 return redirect()
    一次线上问题引发的思考
    一次前端体验优化
    RSA For PHP
    判断是否字符串是否是JSON
    过滤Xss
    Yii2 中日志的记录
    Yii2 中禁用csrf校验
    开始。
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10116784.html
Copyright © 2011-2022 走看看