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

  • 相关阅读:
    es5预览本地文件、es6练习代码演示案例
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 836 矩形重叠(暴力)
    Subversion under Linux [Reprint]
    Subversion how[Reprint]
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6259621.html
Copyright © 2011-2022 走看看