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

    1565: [NOI2009]植物大战僵尸

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 2317  Solved: 1071
    [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

    分析:

    看到这题就觉得亲切,这不是最大权闭合子图么...被保护的点向保护它的点连边,然后就是裸的最大权闭合子图...

    但是发现过不了样例...TAT...因为有环...

    所以我们要要删掉环的点,并且如果环上的点不能选,那么指向它的点也不能选...怎么办?拓扑排序?

    但是拓扑排序只能判断有没有环,不能判断点是否在环上...比如下面这张图...

    但是很巧的是我们的图是所有指向环的点都不能选...所以反向所有边...拓扑排序无法访问到的点就是需要删掉的点...(WA了好久QAQ...感谢LMY...)

    代码:

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<queue>
     6 //by NeighThorn
     7 #define inf 0x7fffffff
     8 using namespace std;
     9   
    10 const int maxn=700+5,maxm=2000000+5;
    11   
    12 int n,m,S,T,cnt,ans,hd[maxn],fl[maxm],in[maxn],to[maxm],nxt[maxm],pos[maxn],val[maxn],vis[maxn],mp[maxn][maxn];
    13   
    14 inline bool bfs(void){
    15     memset(pos,-1,sizeof(pos));
    16     int head=0,tail=0,q[maxn];
    17     q[0]=S,pos[S]=0;
    18     while(head<=tail){
    19         int top=q[head++];
    20         for(int i=hd[top];i!=-1;i=nxt[i])
    21             if(pos[to[i]]==-1&&fl[i])
    22                 pos[to[i]]=pos[top]+1,q[++tail]=to[i];
    23     }
    24     return pos[T]!=-1;
    25 }
    26   
    27 inline int find(int v,int f){
    28     if(v==T)
    29         return f;
    30     int res=0,t;
    31     for(int i=hd[v];i!=-1&&f>res;i=nxt[i])
    32         if(pos[to[i]]==pos[v]+1&&fl[i])
    33             t=find(to[i],min(fl[i],f-res)),fl[i]-=t,fl[i^1]+=t,res+=t;
    34     if(!res)
    35         pos[v]=-1;
    36     return res;
    37 }
    38   
    39 inline int dinic(void){
    40     int res=0,t;
    41     while(bfs())
    42         while(t=find(S,inf))
    43             res+=t;
    44     return res;
    45 }
    46   
    47 inline void topo(void){
    48     queue<int> q;
    49     for(int i=1;i<=n*m;i++)
    50         if(!in[i])
    51             q.push(i),vis[i]=1;
    52     while(!q.empty()){
    53         int top=q.front();q.pop();
    54         for(int i=1;i<=n*m;i++)
    55             if(mp[top][i]){
    56                 in[i]-=mp[top][i];
    57                 if(!in[i])
    58                     q.push(i),vis[i]=1;
    59             }
    60     }
    61 }
    62   
    63 inline void add(int s,int x,int y){
    64     fl[cnt]=s;to[cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt++;
    65     fl[cnt]=0;to[cnt]=x;nxt[cnt]=hd[y];hd[y]=cnt++;
    66 }
    67   
    68 signed main(void){
    69     // freopen("in.txt","r",stdin);
    70     // freopen("out.txt","w",stdout);
    71     memset(in,0,sizeof(in));
    72     memset(hd,-1,sizeof(hd));
    73     scanf("%d%d",&n,&m);T=n*m+1;
    74     for(int i=1,s;i<=n*m;i++){
    75         scanf("%d%d",&val[i],&s);
    76         for(int j=1,x,y;j<=s;j++){
    77             scanf("%d%d",&x,&y),x++,y++;
    78             in[(x-1)*m+y]++;mp[i][(x-1)*m+y]++;
    79         }
    80         if(i%m)
    81             in[i]++,mp[i+1][i]++;
    82     }
    83     topo();
    84     for(int i=1;i<=n*m;i++)
    85         if(vis[i]){
    86             if(val[i]>0)
    87                 ans+=val[i],add(val[i],S,i);
    88             else
    89                 add(-val[i],i,T);
    90             for(int j=1;j<=n*m;j++)
    91                 if(vis[j]&&mp[i][j])
    92                     add(inf,j,i);
    93         }
    94     printf("%d
    ",max(ans-dinic(),0));
    95     return 0;   
    96 }//Cap ou pas cap. Cap.

    By NeighThorn

  • 相关阅读:
    Codeforces #533 div2 做题记录
    算法竞赛模板 打印素数表
    算法竞赛模板 计算组合数
    Educational Codeforces Round 34 (Rated for Div. 2)
    ACM感悟 -----sdust
    Codeforces Round #450 (Div. 2)
    EOJ Monthly 2017.12
    Wannafly挑战赛5
    二分图匹配
    今日颓废
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6259621.html
Copyright © 2011-2022 走看看