BZOJ 1565 植物大战僵尸

http://www.lydsy.com/JudgeOnline/problem.php?id=1565

思路:由于植物之间有保护关系:(右边的植物保护左边的植物,植物攻击范围内的植物都被保护了),因此可以用最大权闭合子图。

  1 #include<algorithm>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<iostream>
  6 #define inf 0x7fffffff
  7 struct edge{
  8     int u,v;
  9 }e[500005];
 10 int tot,go[500005],first[500005],next[500005],flow[500005];
 11 int op[500005],cnt[500005],dis[500005],n,m,mx[20005],all,ru[500005];
 12 int id[105][105],w[105][105],S,T,nodes,pd[500005],c[500005];
 13 int read(){
 14     int t=0,f=1;char ch=getchar();
 15     while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
 16     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
 17     return t*f;
 18 }
 19 void insert(int x,int y,int z){
 20     tot++;
 21     go[tot]=y;
 22     next[tot]=first[x];
 23     first[x]=tot;
 24     flow[tot]=z;
 25 }
 26 void add(int x,int y,int z){
 27     insert(x,y,z);op[tot]=tot+1;
 28     insert(y,x,0);op[tot]=tot-1;
 29 }
 30 int dfs(int x,int f){
 31     if (x==T) return f;
 32     int sum=0,mn=nodes;
 33     for (int i=first[x];i;i=next[i]){
 34         int pur=go[i];
 35         if (flow[i]&&dis[pur]+1==dis[x]){
 36             int save=dfs(pur,std::min(f-sum,flow[i]));
 37             sum+=save;
 38             flow[i]-=save;
 39             flow[op[i]]+=save;
 40             if (sum==f||dis[S]>=nodes) return sum;
 41         }
 42         if (flow[i]) mn=std::min(mn,dis[pur]);
 43     }
 44     if (sum==0){
 45         cnt[dis[x]]--;
 46         if (cnt[dis[x]]==0){
 47             dis[S]=nodes;
 48         }else{
 49             dis[x]=mn+1;
 50             cnt[dis[x]]++;
 51         }
 52     }
 53     return sum;
 54 }
 55 int main(){
 56     n=read();m=read();
 57     S=0;nodes=1;
 58     for (int i=1;i<=n;i++)
 59      for (int j=1;j<=m;j++)
 60       id[i][j]=nodes++;
 61     for (int i=1;i<=n;i++)
 62      for (int j=1;j<=m;j++){    
 63         w[i][j]=read();
 64         int num=read();
 65         for (int k=1;k<=num;k++){
 66             int x=read(),y=read();
 67             x++;y++;
 68             e[++all].u=id[i][j],e[all].v=id[x][y],ru[e[all].v]++;
 69         }
 70     }
 71     for (int i=1;i<=n;i++)
 72      for (int j=m;j>1;j--)
 73       e[++all].u=id[i][j],e[all].v=id[i][j-1],ru[id[i][j-1]]++;
 74     for (int i=1;i<=all;i++)
 75      insert(e[i].u,e[i].v,0);
 76     T=nodes;nodes++;
 77     int top=0;
 78     for (int i=1;i<=nodes-1;i++)
 79      if (ru[i]==0)
 80       pd[i]=1,c[++top]=i;
 81     while (top>0){
 82         int now=c[top--];
 83         for (int i=first[now];i;i=next[i]){
 84             int pur=go[i];
 85             ru[pur]--;
 86             if (ru[pur]==0){
 87                 pd[pur]=1;
 88                 c[++top]=pur;
 89             }
 90         }
 91     }  
 92     tot=0;
 93     for (int i=1;i<=nodes;i++)
 94       first[i]=0;
 95     for (int i=1;i<=all;i++)
 96      if (pd[e[i].u]&&pd[e[i].v])
 97       add(e[i].u,e[i].v,inf);
 98     int sum=0;  all=0;
 99     for (int i=1;i<=n;i++)
100      for (int j=1;j<=m;j++)
101       if (pd[id[i][j]]){
102             if (w[i][j]>0) add(id[i][j],T,w[i][j]),sum+=w[i][j];
103             else 
104             if (w[i][j]<0) add(S,id[i][j],-w[i][j]);
105             all++;
106       }   
107     nodes=all;
108     int ans=0;
109     while (dis[S]<nodes) ans+=dfs(S,inf);       
110     printf("%d\n",sum-ans); 
111 }

 

posted @ 2016-06-12 20:03  GFY  阅读(226)  评论(0编辑  收藏  举报