zoukankan      html  css  js  c++  java
  • 【最大权闭合子图 tarjan】bzoj1565: [NOI2009]植物大战僵尸

    dinic+tarjan板子练手题

    Description

    Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏。Plants(植物)和Zombies(僵尸)是游戏的主角,其
    中Plants防守,而Zombies进攻。该款游戏包含多种不同的挑战系列,比如Protect Your Brain、Bowling等等。其
    中最为经典的,莫过于玩家通过控制Plants来防守Zombies的进攻,或者相反地由玩家通过控制Zombies对Plants发
    起进攻。
     
    现在,我们将要考虑的问题是游戏中Zombies对Plants的进攻,请注意,本题中规则与实际游戏有所不同。游戏中
    有两种角色,Plants和Zombies,每个Plant有一个攻击位置集合,它可以对这些位置进行保护;而Zombie进攻植物
    的方式是走到植物所在的位置上并将其吃掉。
     
    游戏的地图可以抽象为一个N行M列的矩阵,行从上到下用0到N–1编号,列从左到右用0到M–1编号;在地图的每个
    位置上都放有一个Plant,为简单起见,我们把位于第r行第c列的植物记为Pr, c。
     
    Plants分很多种,有攻击类、防守类和经济类等等。为了简单的描述每个Plant,定义Score和Attack如下:
     
    Score[Pr, c]
     
    Zombie击溃植物Pr, c可获得的能源。若Score[Pr, c]为非负整数,则表示击溃植物Pr, c可获得能源Score[Pr, c]
    ,若为负数表示击溃Pr, c需要付出能源 -Score[Pr, c]。
     
    Attack[Pr, c]
     
    植物Pr, c能够对Zombie进行攻击的位置集合。
     
    Zombies必须从地图的右侧进入,且只能沿着水平方向进行移动。Zombies攻击植物的唯一方式就是走到该植物所在
    的位置并将植物吃掉。因此Zombies的进攻总是从地图的右侧开始。也就是说,对于第r行的进攻,Zombies必须首
    先攻击Pr, M-1;若需要对Pr, c(0 ≤ c < M-1)攻击,必须将Pr,M-1, Pr, M-2 … Pr, c+1先击溃,并移动到位
    置(r, c)才可进行攻击。
     
    在本题的设定中,Plants的攻击力是无穷大的,一旦Zombie进入某个Plant的攻击位置,该Zombie会被瞬间消灭,
    而该Zombie没有时间进行任何攻击操作。因此,即便Zombie进入了一个Plant所在的位置,但该位置属于其他植物
    的攻击位置集合,则Zombie会被瞬间消灭而所在位置的植物则安然无恙(在我们的设定中,Plant的攻击位置不包
    含自身所在位置,否则你就不可能击溃它了)。
     
    Zombies的目标是对Plants的阵地发起进攻并获得最大的能源收入。每一次,你可以选择一个可进攻的植物进行攻
    击。本题的目标为,制定一套Zombies的进攻方案,选择进攻哪些植物以及进攻的顺序,从而获得最大的能源收入

    Input

    第一行包含两个整数N, M,分别表示地图的行数和列数。
    接下来N×M行描述每个位置上植物的信息。第r×M + c + 1行按照如下格式给出植物Pr, c的信息:
    第一个整数为Score[Pr, c], 第二个整数为集合Attack[Pr, c]中的位置个数w,
    接下来w个位置信息(r’, c’),表示Pr, c可以攻击位置第r’ 行第c’ 列。
    1 ≤ N ≤ 20,1 ≤ M ≤ 30,-10000 ≤ Score ≤ 10000 。
     

    Output

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

    题目大意

    每种植物有若干个可保护的点,且僵尸消灭每种植物都会有特定权值。僵尸必须从右边进入,依次消灭没有被任何植物植物保护的植物。求僵尸能够获得的最大价值。

    题目分析

    放上来当板子看吧

    第一发写的时候zz了,把恒存在的植物环的所有出边给删了……

      1 #include<bits/stdc++.h>
      2 const int maxn = 33;
      3 const int maxNode = 5035;
      4 const int maxm = 1000035;
      5 const int INF = 2e9;
      6 
      7 struct Edge
      8 {
      9     int u,v,f,c;
     10     Edge(int a=0, int b=0, int c=0, int d=0):u(a),v(b),f(c),c(d) {}
     11 }edges[maxm];
     12 int r,c,S,T,ans;
     13 int v[maxn][maxn],id[maxn][maxn];
     14 int edgeTot,head[maxNode],nxt[maxm],lv[maxNode];
     15 int low[maxNode],dfn[maxNode],tim;
     16 int stk[maxNode],top,col[maxNode],cols,size[maxNode];
     17 
     18 int read()
     19 {
     20     char ch = getchar();
     21     int num = 0, fl = 1;
     22     for (; !isdigit(ch); ch=getchar())
     23         if (ch=='-') fl = -1;
     24     for (; isdigit(ch); ch=getchar())
     25         num = (num<<1)+(num<<3)+ch-48;
     26     return num*fl;
     27 }
     28 void addedge(int u, int v, int c)
     29 {
     30     edges[edgeTot] = Edge(u, v, 0, c), nxt[edgeTot] = head[u], head[u] = edgeTot, ++edgeTot;
     31     edges[edgeTot] = Edge(v, u, 0, 0), nxt[edgeTot] = head[v], head[v] = edgeTot, ++edgeTot;
     32 }
     33 bool buildLevel()
     34 {
     35     std::queue<int> q;
     36     memset(lv, 0, sizeof lv);
     37     q.push(S), lv[S] = 1;
     38     for (int tmp; q.size(); )
     39     {
     40         tmp = q.front(), q.pop();
     41         for (int i=head[tmp]; i!=-1; i=nxt[i])
     42         {
     43             int v = edges[i].v;
     44             if (!lv[v]&&edges[i].f < edges[i].c){
     45                 lv[v] = lv[tmp]+1, q.push(v);
     46                 if (v==T) return true;
     47             }
     48         }
     49     }
     50     return false;
     51 }
     52 int fndPath(int x, int lim)
     53 {
     54     int sum = 0;
     55     if (x==T||!lim) return lim;
     56     for (int i=head[x]; i!=-1&&sum < lim; i=nxt[i])
     57     {
     58         int v = edges[i].v, val;
     59         if (lv[v]==lv[x]+1&&edges[i].f < edges[i].c){
     60             if ((val = fndPath(v, std::min(lim-sum, edges[i].c-edges[i].f)))){
     61                 sum += val, edges[i].f += val, edges[i^1].f -= val;
     62             }else lv[v] = -1;
     63         }
     64     }
     65     return sum;
     66 }
     67 int dinic()
     68 {
     69     int ret = 0, val;
     70     while (buildLevel())
     71         while ((val = fndPath(S, INF))) ret += val;
     72     return ret;
     73 }
     74 void tarjan(int x)
     75 {
     76     dfn[x] = low[x] = ++tim, stk[++top] = x;
     77     for (int i=head[x]; i!=-1; i=nxt[i])
     78         if ((i&1)==0){
     79             int v = edges[i].v;
     80             if (!dfn[v]) tarjan(v), low[x] = std::min(low[x], low[v]);
     81             else if (!col[v]) low[x] = std::min(low[x], dfn[v]);
     82         }
     83     if (low[x]==dfn[x]){
     84         col[x] = ++cols, size[cols] = 1;
     85         for (; stk[top]!=x; --top)
     86             col[stk[top]] = cols, ++size[cols];
     87         --top;
     88     }
     89 }
     90 int main()
     91 {
     92     memset(head, -1, sizeof head);
     93     r = read(), c = read(), S = 0, T = r*c+1;
     94     for (int i=1, cnt=0; i<=r; i++)
     95         for (int j=1; j<=c; j++)
     96             id[i][j] = ++cnt;
     97     for (int i=1; i<=r; i++)
     98         for (int j=1; j<=c; j++)
     99         {
    100             v[i][j] = read();
    101             if (j!=c) addedge(id[i][j], id[i][j+1], INF);
    102             for (int k=read(); k; k--)
    103                 addedge(id[read()+1][read()+1], id[i][j], INF);
    104         }
    105     for (int i=1; i<=r*c; i++)
    106         if (!dfn[i]) tarjan(i);
    107     for (int i=1; i<=r; i++)
    108         for (int j=1; j<=c; j++)
    109             if (size[col[id[i][j]]]==1){
    110                 if (v[i][j] < 0) addedge(id[i][j], T, -v[i][j]);
    111                 else addedge(S, id[i][j], v[i][j]), ans += v[i][j];
    112             }
    113     printf("%d
    ",ans-dinic());
    114     return 0;
    115 }

    END

  • 相关阅读:
    Maidsafe-去中心化互联网白皮书
    The Top 20 Cybersecurity Startups To Watch In 2021 Based On Crunchbase
    Top 10 Blockchain Security and Smart Contract Audit Companies
    The 20 Best Cybersecurity Startups To Watch In 2020
    Blockchain In Cybersecurity: 11 Startups To Watch In 2019
    004-STM32+BC26丨260Y基本控制篇(阿里云物联网平台)-在阿里云物联网平台上一型一密动态注册设备(Android)
    涂鸦开发-单片机+涂鸦模组开发+OTA
    000-ESP32学习开发-ESP32烧录板使用说明
    03-STM32+Air724UG远程升级篇OTA(阿里云物联网平台)-STM32+Air724UG使用阿里云物联网平台OTA远程更新STM32程序
    03-STM32+Air724UG远程升级篇OTA(自建物联网平台)-STM32+Air724UG实现利用http/https远程更新STM32程序(TCP指令,单片机程序检查更新)
  • 原文地址:https://www.cnblogs.com/antiquality/p/10513273.html
Copyright © 2011-2022 走看看