zoukankan      html  css  js  c++  java
  • BZOJ 1565: [NOI2009]植物大战僵尸

    1565: [NOI2009]植物大战僵尸

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 2318  Solved: 1072
    [Submit][Status][Discuss]

    Description

    Input

    Output

    仅包含一个整数,表示可以获得的最大能源收入。注意,你也可以选择不进行任何攻击,这样能源收入为0。

    Sample Input

    3 2
    10 0
    20 0
    -10 0
    -5 1 0 0
    100 1 2 1
    100 0

    Sample Output

    25

    HINT

    在样例中, 植物P1,1可以攻击位置(0,0), P2, 0可以攻击位置(2,1)。 
    一个方案为,首先进攻P1,1, P0,1,此时可以攻击P0,0 。共得到能源收益为(-5)+20+10 = 25。注意, 位置(2,1)被植物P2,0保护,所以无法攻击第2行中的任何植物。 
    【大致数据规模】
    约20%的数据满足1 ≤ N, M ≤ 5;
    约40%的数据满足1 ≤ N, M ≤ 10;
    约100%的数据满足1 ≤ N ≤ 20,1 ≤ M ≤ 30,-10000 ≤ Score ≤ 10000 。

    Source

     
    [Submit][Status][Discuss]

    推荐一下僧仙的题解,很好的。

    这叫什么最大权闭合子图问题,额,好听死了。

    首先,如果有形如A保护B,B保护A这样的扯淡关系,那么A和B都不能吃。

    按照保护关系建出有向图后拓扑排序可以筛出这些顽强的植物,并把它们从题中永久删除。

    可以把最终得分,转换为所有正权之和,减去选取的负权之和,减去未选取的正权之和,咦,这东西可以最小割了……

      1 #include <cstdio>
      2 #include <cstring>
      3 
      4 inline int nextChar(void)
      5 {
      6     const static int siz = 1024;
      7     
      8     static char buf[siz];
      9     static char *hd = buf + siz;
     10     static char *tl = buf + siz;
     11     
     12     if (hd == tl)
     13         fread(hd = buf, 1, siz, stdin);
     14         
     15     return *hd++;
     16 }
     17 
     18 inline int nextInt(void)
     19 {
     20     register int ret = 0;
     21     register int neg = false;
     22     register int bit = nextChar();
     23     
     24     for (; bit < 48; bit = nextChar())
     25         if (bit == '-')neg ^= true;
     26         
     27     for (; bit > 47; bit = nextChar())
     28         ret = ret * 10 + bit - 48;
     29         
     30     return neg ? -ret : ret;
     31 }
     32 
     33 const int siz = 500005;
     34 const int inf = 1000000007;
     35 
     36 int n, m;
     37 int S[1005];
     38 int P[55][55];
     39 
     40 inline void getP(void)
     41 {
     42     int tot = 0;
     43     
     44     for (int i = 1; i <= n; ++i)
     45         for (int j = 1; j <= m; ++j)
     46             P[i][j] = ++tot;
     47 }
     48 
     49 namespace flow
     50 {
     51     int s, t;
     52     int hd[siz];
     53     int nt[siz];
     54     int fl[siz];
     55     int to[siz];
     56     
     57     int dep[siz];
     58     
     59     inline bool bfs(void)
     60     {
     61         static int que[siz], head, tail;
     62         memset(dep, 0, sizeof(dep));
     63         head = 0, tail = 0;
     64         que[tail++] = s;
     65         dep[s] = 1;
     66         
     67         while (head != tail)
     68         {
     69             int u = que[head++], v;
     70             
     71             for (int i = hd[u]; ~i; i = nt[i])
     72                 if (!dep[v = to[i]] && fl[i])
     73                     dep[que[tail++] = v] = dep[u] + 1;
     74         }
     75         
     76         return dep[t];
     77     }
     78     
     79     int cur[siz];
     80     
     81     int dfs(int u, int f)
     82     {
     83         if (u == t || !f)
     84             return f;
     85             
     86 //        printf("dfs %d %d
    ", u, f);
     87         
     88         int used = 0, flow, v;
     89         
     90         for (int i = hd[u]; ~i; i = nt[i])
     91             if (dep[v = to[i]] == dep[u] + 1 && fl[i])    
     92             {
     93                 if (f - used < fl[i])
     94                     flow = dfs(v, f - used);
     95                 else
     96                     flow = dfs(v, fl[i]);
     97                 
     98                 used += flow;
     99                 fl[i] -= flow;
    100                 fl[i^1] += flow;
    101                 
    102                 if (used == f)
    103                     return f;
    104                     
    105                 if (fl[i])
    106                     cur[u] = i;
    107             }
    108         
    109         if (!used)
    110             dep[u] = 0;
    111             
    112         return used;
    113     }
    114     
    115     inline int solve(void)
    116     {
    117         int maxFlow = 0, newFlow;
    118         
    119         while (bfs())
    120         {
    121             for (int i = s; i <= t; ++i)
    122                 cur[i] = hd[i];
    123             while (newFlow = dfs(s, inf))
    124                 maxFlow += newFlow;
    125         }
    126         
    127         return maxFlow;
    128     }
    129 }
    130 
    131 inline void add(int u, int v, int f)
    132 {
    133 //    printf("add %d %d %d
    ", u, v, f);
    134     
    135     using namespace flow;
    136     
    137     static int tot = 0;
    138     static int flg = 0;
    139     
    140     if (!flg)
    141         memset(hd, -1, sizeof(hd)), flg = 1;
    142         
    143     nt[tot] = hd[u]; to[tot] = v; fl[tot] = f; hd[u] = tot++;
    144     nt[tot] = hd[v]; to[tot] = u; fl[tot] = 0; hd[v] = tot++;
    145 }
    146 
    147 namespace turpo
    148 {
    149     int hd[siz];
    150     int to[siz];
    151     int nt[siz];
    152     int cnt[siz];
    153     int vis[siz];
    154     
    155     inline void solve(void)
    156     {
    157         static int que[siz], head, tail;
    158         
    159         for (int i = 1; i <= P[n][m]; ++i)
    160             if (!cnt[i])que[tail++] = i;
    161             
    162         while (head != tail)
    163         {
    164             int u = que[head++], v;
    165             
    166             vis[u] = true;
    167             
    168             for (int i = hd[u]; ~i; i = nt[i])
    169                 if (--cnt[v = to[i]] == 0)que[tail++] = v;
    170         }
    171         
    172 //        for (int i = 1; i <= P[n][m]; ++i)
    173 //            printf("%d : %d
    ", i, vis[i]);
    174         
    175         for (int i = 1; i <= P[n][m]; ++i)
    176             for (int j = hd[i]; ~j; j = nt[j])
    177                 if (vis[i] && vis[to[j]])
    178                     add(to[j], i, inf);
    179     }
    180 }
    181 
    182 inline void addEdge(int u, int v)
    183 {
    184 //    printf("addEdge %d %d
    ", u, v);
    185     
    186     using namespace turpo;
    187     
    188     static int tot = 0;
    189     static int flg = 0;
    190     
    191     if (!flg)
    192         memset(hd, -1, sizeof(hd)), flg = 1;
    193     
    194     nt[tot] = hd[u]; to[tot] = v; hd[u] = tot++; ++cnt[v];
    195 }
    196 
    197 signed main(void)
    198 {
    199     n = nextInt();
    200     m = nextInt();
    201     
    202     int sum = 0;
    203     
    204     getP();
    205     
    206     for (int i = 1; i <= n; ++i)
    207         for (int j = 1; j <= m; ++j)
    208         {
    209             S[P[i][j]] = nextInt();
    210             
    211             for (int k = nextInt(); k--; )
    212             {
    213                 int x = nextInt() + 1;
    214                 int y = nextInt() + 1;
    215                 
    216                 addEdge(P[i][j], P[x][y]);
    217             }
    218             
    219             if (j > 1)
    220                 addEdge(P[i][j], P[i][j - 1]);
    221         }
    222         
    223     turpo::solve();
    224     
    225     flow::s = 0;
    226     flow::t = P[n][m] + 1;
    227     
    228     for (int i = 1; i <= P[n][m]; ++i)
    229         if (turpo::vis[i])
    230         {
    231             if (S[i] < 0)
    232                 add(i, flow::t, -S[i]);
    233             else
    234                 add(flow::s, i, S[i]), sum += S[i];
    235         }
    236         
    237     printf("%d
    ", sum - flow::solve());
    238 }

    @Author: YouSiki

  • 相关阅读:
    ACdream 1069 无耻的出题人
    ACdream 1064 完美数
    ACdream 1028 Path
    ACdream 1020 The Game about KILL
    ACdream 1015 Double Kings
    CodeForces
    Codeforces 390A( 模拟题)
    Codeforces 389B(十字模拟)
    Codeforces 389A (最大公约数)
    Codeforces 417 C
  • 原文地址:https://www.cnblogs.com/yousiki/p/6259802.html
Copyright © 2011-2022 走看看