bzoj 1565: [NOI2009]植物大战僵尸

  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #define M 1000
  7 #define N 360000
  8 #define inf 2139062143
  9 using namespace std;
 10 int cnt=1,n,m,S,T,d[M],q[M],f[M],head[M],next[N],u[N],v[N],a[M],head1[M],next1[N],u1[N],du[N],cnt1;
 11 int ans,sum;
 12 bool bfs()
 13 {
 14     memset(d,0,sizeof(d));
 15     int h=0,t=1;
 16     q[1]=S;
 17     d[S]=1;
 18     for(;h<t;)
 19       {
 20         h++;
 21         int p=q[h];
 22         for(int i=head[p];i;i=next[i])
 23           if(!d[u[i]]&&v[i])
 24             {
 25                 d[u[i]]=d[p]+1;
 26                 if(d[T])
 27                   return 1;
 28                 t++;
 29                 q[t]=u[i];
 30             }
 31       }
 32     return 0;
 33 }
 34 int dinic(int s,int f)
 35 {
 36     if(s==T)
 37       return f;
 38     int rest=f;
 39     for(int i=head[s];i&&rest;i=next[i])
 40       if(v[i]&&d[u[i]]==d[s]+1)
 41         {
 42             int now=dinic(u[i],min(rest,v[i]));
 43             if(!now)
 44               d[u[i]]=0;
 45             v[i]-=now;
 46             v[i^1]+=now;
 47             rest-=now;
 48         }
 49     return f-rest;  
 50 }
 51 void jia1(int a1,int a2,int a3)
 52 {
 53     cnt++;
 54     next[cnt]=head[a1];
 55     head[a1]=cnt;
 56     u[cnt]=a2;
 57     v[cnt]=a3;
 58     return;
 59 }
 60 void jia(int a1,int a2,int a3)
 61 {
 62     jia1(a1,a2,a3);
 63     jia1(a2,a1,0);
 64     return;
 65 }
 66 int main()
 67 {
 68     scanf("%d%d",&n,&m);
 69     S=0;
 70     T=n*m+1;
 71     for(int i=1;i<=n;i++)
 72       for(int j=1;j<=m;j++)
 73         {
 74             int a2,a3,a4,a5,a6;
 75             a6=(i-1)*m+j;
 76             scanf("%d%d",&a[a6],&a2);
 77             for(int k=1;k<=a2;k++)
 78               {
 79                 scanf("%d%d",&a3,&a4);
 80                 a3++;
 81                 a4++;
 82                 a5=(a3-1)*m+a4;
 83                 cnt1++;
 84                 next1[cnt1]=head1[a6];
 85                 head1[a6]=cnt1;
 86                 du[a5]++;
 87                 u1[cnt1]=a5;
 88               }
 89         }
 90     for(int i=1;i<=n;i++)
 91       for(int j=1;j)
 92         {
 93             int a1=(i-1)*m+j,a2=(i-1)*m+j+1;
 94             cnt1++;
 95             next1[cnt1]=head1[a2];
 96             head1[a2]=cnt1;
 97             du[a1]++;
 98             u1[cnt1]=a1;
 99         }
100     int h=0,t=0;
101     for(int i=1;i<=n*m;i++)
102       if(!du[i])
103         q[++t]=i;
104     for(;h<t;)
105       {
106         h++;
107         for(int i=head1[q[h]];i;i=next1[i])
108           {
109             du[u1[i]]--;
110             if(!du[u1[i]])
111               q[++t]=u1[i];
112           }
113       }
114     for(int i=1;i<=n;i++)
115       for(int j=1;j<=m;j++)
116         if(!du[(i-1)*m+j])
117           {
118             int a1=(i-1)*m+j;
119             if(a[a1]>0)
120               {
121                 jia(a1,T,a[a1]);
122                 sum+=a[a1];
123               }
124             else
125               jia(S,a1,-a[a1]);
126             for(int k=head1[a1];k;k=next1[k])
127               if(!du[u1[k]])
128                 jia(a1,u1[k],inf);
129           }
130     for(;bfs();)
131       ans+=dinic(S,inf);
132     printf("%d\n",sum-ans);
133     return 0;
134 }

首先我们要把互相保护的去掉,在右边的肯定保护它左边的,还有题目中原先的保护条件 进行建边,拓扑排序去掉永远吃不掉的。然后把所有边反向就是一个最大权闭合子图,正权点向

汇点建边,容量为权值。源点向负权点建边,容量为权值相反数,原图中的边容量为inf,答案为正权值和减去最小割。

转载于:https://www.cnblogs.com/xydddd/p/5277401.html

你可能感兴趣的:(bzoj 1565: [NOI2009]植物大战僵尸)