• 洛谷P2805 植物大战僵尸


    题意:给你一张图,每个节点保护若干节点。

    当一个节点不被保护的时候,你就可以gay掉它。

    gay每个节点都有收益(可能为负),求最大总收益。

    解:首先发现是一个最大权闭合子图。

    把保护关系变成被保护,那么gay每个节点就必须gay每个保护它的节点。

    然后发现有个小问题:有环。

    于是我们tarjan求强连通分量然后删点。最后最大权闭合子图。

    这里我删点删的十分暴力......(反正点不多)

    注意:删点的时候,如果它权值为正,要在sum里面减去它的权值。

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <queue>
      4 #include <cstring>
      5 #include <stack>
      6 
      7 const int N = 1010, M = 1000010, INF = 0x3f3f3f3f;
      8 
      9 struct Edge {
     10     int nex, v, c;
     11 }edge[M << 1], _edge[M]; int top = 1, _top;
     12 
     13 int e[N], d[N], _e[N];
     14 std::queue<int> Q;
     15 std::stack<int> S;
     16 int dfn[N], low[N], num, fr[N], scc_cnt, scc_siz[N], vis[N], val[N], sum;
     17 
     18 void tarjan(int x) {
     19     dfn[x] = low[x] = ++num;
     20     S.push(x);
     21     for(int i = _e[x]; i; i = _edge[i].nex) {
     22         int y = _edge[i].v;
     23         if(!dfn[y]) {
     24             tarjan(y);
     25             low[x] = std::min(low[x], low[y]);
     26         }
     27         else if(!fr[y]) {
     28             low[x] = std::min(low[x], dfn[y]);
     29         }
     30     }
     31     if(low[x] == dfn[x]) {
     32         scc_cnt++;
     33         int y;
     34         do {
     35             y = S.top();
     36             S.pop();
     37             fr[y] = scc_cnt;
     38             scc_siz[scc_cnt]++;
     39         } while(y != x);
     40     }
     41     return;
     42 }
     43 
     44 inline void add(int x, int y, int z) {
     45     top++;
     46     edge[top].v = y;
     47     edge[top].c = z;
     48     edge[top].nex = e[x];
     49     e[x] = top;
     50 
     51     top++;
     52     edge[top].v = x;
     53     edge[top].c = 0;
     54     edge[top].nex = e[y];
     55     e[y] = top;
     56     return;
     57 }
     58 
     59 inline void _add(int x, int y) {
     60     _top++;
     61     _edge[_top].v = y;
     62     _edge[_top].nex = _e[x];
     63     _e[x] = _top;
     64     return;
     65 }
     66 
     67 void del(int x) {
     68     vis[x] = 1;
     69     if(val[x] > 0) {
     70         sum -= val[x];
     71     }
     72     for(int i = e[x]; i; i = edge[i].nex) {
     73         edge[i].c = edge[i ^ 1].c = 0;
     74     }
     75     for(int i = _e[x]; i; i = _edge[i].nex) {
     76         int y = _edge[i].v;
     77         if(!vis[y]) {
     78             del(y);
     79         }
     80     }
     81     e[x] = _e[x] = 0;
     82     return;
     83 }
     84 
     85 inline bool BFS(int s, int t) {
     86     memset(d, 0, sizeof(d));
     87     d[s] = 1;
     88     Q.push(s);
     89     while(!Q.empty()) {
     90         int x = Q.front();
     91         Q.pop();
     92         for(int i = e[x]; i; i = edge[i].nex) {
     93             int y = edge[i].v;
     94             if(!edge[i].c || d[y]) {
     95                 continue;
     96             }
     97             d[y] = d[x] + 1;
     98             Q.push(y);
     99         }
    100     }
    101     return d[t];
    102 }
    103 
    104 int DFS(int x, int t, int maxF) {
    105     if(x == t) {
    106         return maxF;
    107     }
    108     int ans = 0;
    109     for(int i = e[x]; i; i = edge[i].nex) {
    110         int y = edge[i].v;
    111         if(!edge[i].c || d[x] + 1 != d[y]) {
    112             continue;
    113         }
    114         int temp = DFS(y, t, std::min(edge[i].c, maxF - ans));
    115         if(!temp) {
    116             d[y] = INF;
    117         }
    118         ans += temp;
    119         edge[i].c -= temp;
    120         edge[i ^ 1].c += temp;
    121         if(ans == maxF) {
    122             break;
    123         }
    124     }
    125     return ans;
    126 }
    127 
    128 inline int solve(int s, int t) {
    129     int ans = 0;
    130     while(BFS(s, t)) {
    131         ans += DFS(s, t, INF);
    132     }
    133     return ans;
    134 }
    135 
    136 int m;
    137 inline int id(int x, int y) {
    138     return (x - 1) * m + y;
    139 }
    140 
    141 int main() {
    142 
    143     int n;
    144     scanf("%d%d", &n, &m);
    145     int s = n * m + 1, t = n * m + 2;
    146     for(int i = 1; i <= n; i++) {
    147         for(int j = 1; j <= m; j++) {
    148             int x, y, z;
    149             scanf("%d", &x);
    150             val[id(i, j)] = x;
    151             if(x > 0) {
    152                 add(s, id(i, j), x);
    153                 sum += x;
    154             }
    155             else if(x < 0) {
    156                 add(id(i, j), t, -x);
    157             }
    158             scanf("%d", &z);
    159             for(int k = 1; k <= z; k++) {
    160                 scanf("%d%d", &x, &y);
    161                 x++;
    162                 y++;
    163                 add(id(x, y), id(i, j), INF);
    164                 _add(id(i, j), id(x, y));
    165             }
    166             if(j < m) {
    167                 add(id(i, j), id(i, j + 1), INF);
    168                 _add(id(i, j + 1), id(i, j));
    169             }
    170         }
    171     }
    172     for(int i = 1; i <= n * m; i++) {
    173         if(!dfn[i]) {
    174             tarjan(i);
    175         }
    176     }
    177     for(int i = 1; i <= n * m; i++) {
    178         if(scc_siz[fr[i]] > 1 && !vis[i]) {
    179             del(i);
    180         }
    181     }
    182     printf("%d", sum - solve(s, t));
    183     return 0;
    184 }
    AC代码
  • 相关阅读:
    ELK
    alerta 集中化告警信息 -zabbix
    Python安装第三方模块出错 No module named setuptools
    Centos7 搭建bind9.9
    DNS 处理模块 dnspython
    varnish 项目实战
    中文版Postman测试需要登陆才能访问的接口(基于Cookie)
    fireFox模拟 post请求、上传插件,火狐浏览器中文postman插件
    MySQL单表最大记录数不能超过多少?
    ApiPost(中文版postman)如何发送一个随机数或者时间戳?
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10116471.html
Copyright © 2020-2023  润新知