bzoj 1565 [NOI2009]植物大战僵尸
Posted dugudashen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于bzoj 1565 [NOI2009]植物大战僵尸的主要内容,如果未能解决你的问题,请参考以下文章
[bzoj1565][NOI2009]植物大战僵尸_网络流_拓扑排序