bzoj 1565 [NOI2009]植物大战僵尸

拓扑排序+最小割。

每个植物有它保护的一些植物,等价于选一些点的先决条件是其它一些点,最大权闭合子图问题。

发现图里有环,所以环里的点都不能选,先决条件是环里的点的点也不能选,所以把所有边反向拓扑排序,拓扑不到的点不能选。

无视掉不能选的点后裸最大权闭合子图建图就好了。

一个最大权闭合子图裸题的题解

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<algorithm>
  5 #include<queue>
  6 using namespace std;
  7 const int dian=605;
  8 const int bian=1000005;
  9 const int INF=0x3f3f3f3f;
 10 int h[dian],nxt[bian],ver[bian],val[bian],ch[dian],cr[dian];
 11 int qz[dian],num[dian],dbh[dian][dian],in[dian],v[dian];
 12 int n,m,tot,aa,bb,cc,ans;
 13 int S,T;
 14 int bh(int a,int b){
 15     return (a-1)*m+b;
 16 }
 17 void add1(int a,int b){
 18     tot++;ver[tot]=b;nxt[tot]=h[a];h[a]=tot;in[b]++;
 19 }
 20 void toposort(){
 21     queue<int>q;
 22     for(int i=1;i<=n*m;i++)
 23         if(!in[i])
 24             q.push(i);
 25     while(!q.empty()){
 26         int x=q.front();
 27         q.pop();
 28         v[x]=1;
 29         for(int i=h[x];i;i=nxt[i]){
 30             int y=ver[i];
 31             in[y]--;
 32             if(!in[y])
 33                 q.push(y);
 34         }
 35     }
 36 }
 37 void add(int a,int b,int c){
 38     tot++;ver[tot]=b;val[tot]=c;nxt[tot]=h[a];h[a]=tot;
 39     tot++;ver[tot]=a;val[tot]=0;nxt[tot]=h[b];h[b]=tot;
 40 }
 41 bool tell(){
 42     memset(ch,-1,sizeof(ch));
 43     queue<int>q;
 44     q.push(S);
 45     ch[S]=0;
 46     while(!q.empty()){
 47         int t=q.front();
 48         q.pop();
 49         for(int i=h[t];i;i=nxt[i])
 50             if(ch[ver[i]]==-1&&val[i]){
 51                 ch[ver[i]]=ch[t]+1;
 52                 q.push(ver[i]);
 53             }
 54     }
 55     return ch[T]!=-1;
 56 }
 57 int zeng(int a,int b){
 58     if(a==T)
 59         return b;
 60     int r=0;
 61     for(int i=cr[a];i&&b>r;i=nxt[i])
 62         if(ch[ver[i]]==ch[a]+1&&val[i]){
 63             int t=zeng(ver[i],min(b-r,val[i]));
 64             val[i]-=t,r+=t,val[i^1]+=t;
 65             if(val[i])
 66                 cr[a]=i;
 67         }
 68     if(!r)
 69         ch[a]=-1;
 70     return r;
 71 }
 72 int dinic(){
 73     int r=0,t;
 74     while(tell()){
 75         for(int i=1;i<=n*m+2;i++)
 76             cr[i]=h[i];
 77         while(t=zeng(S,INF))
 78             r+=t;
 79     }
 80     return r;
 81 }
 82 int main(){
 83     memset(h,0,sizeof(h));
 84     memset(nxt,0,sizeof(nxt));
 85     memset(num,0,sizeof(num));
 86     memset(in,0,sizeof(in));
 87     memset(v,0,sizeof(v));
 88     tot=0,ans=0;
 89     scanf("%d%d",&n,&m);
 90     S=n*m+1,T=n*m+2;
 91     for(int i=1;i<=n;i++)
 92         for(int j=1;j<=m;j++){
 93             scanf("%d",&aa);
 94             qz[bh(i,j)]=aa;
 95             scanf("%d",&aa);
 96             for(int k=1;k<=aa;k++){
 97                 scanf("%d%d",&bb,&cc);
 98                 num[bh(i,j)]++;
 99                 dbh[bh(i,j)][num[bh(i,j)]]=bh(bb+1,cc+1);
100                 add1(bh(i,j),bh(bb+1,cc+1));
101             }
102         }
103     for(int i=1;i<=n;i++)
104         for(int j=2;j<=m;j++)
105             add1(bh(i,j),bh(i,j-1));
106     toposort();
107     memset(h,0,sizeof(h));
108     memset(nxt,0,sizeof(nxt));
109     tot=1;
110     for(int i=1;i<=n;i++)
111         for(int j=1;j<=m;j++)
112             if(v[bh(i,j)]){
113                 if(qz[bh(i,j)]>0){
114                     ans+=qz[bh(i,j)];
115                     add(S,bh(i,j),qz[bh(i,j)]);
116                 }
117                 else if(qz[bh(i,j)]<0)
118                     add(bh(i,j),T,-qz[bh(i,j)]);
119                 for(int k=1;k<=num[bh(i,j)];k++)
120                     if(v[dbh[bh(i,j)][k]])
121                         add(dbh[bh(i,j)][k],bh(i,j),INF);
122             }
123     for(int i=1;i<=n;i++)
124         for(int j=1;j<m;j++)
125             if(v[bh(i,j)]&&v[bh(i,j+1)])
126                 add(bh(i,j),bh(i,j+1),INF);
127     printf("%d",ans-dinic());
128     return 0;
129 }

 

posted @ 2017-01-11 12:07  dugudashen  阅读(181)  评论(0编辑  收藏  举报