• 【最大权闭合子图 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

  • 相关阅读:
    亚马逊的客户服务和承诺
    亚马逊云主管:我们有可能成为全世界最大的企业公司
    阿里市值超越亚马逊 马云开启下半场技术理想
    股价飙升500倍,市值超过4700亿美元,从网络书店起家的亚马逊凭什么一飞冲天?
    美国女子不断收到中国神秘快递,背后原因竟是刷单
    亚马逊称网络星期一成公司史上“最大的购物日
    万众创业葬送了多少人的前程
    日本企业遭遇严重用工短缺
    培生同意以3亿美元出售华尔街英语
    亚马逊500多名欧洲员工宣布在“黑色星期五”罢工
  • 原文地址:https://www.cnblogs.com/antiquality/p/10513273.html
Copyright © 2020-2023  润新知