1. 程式人生 > >【BZOJ1565】【NOI2009】植物大戰僵屍 網絡流 最大權閉合子圖

【BZOJ1565】【NOI2009】植物大戰僵屍 網絡流 最大權閉合子圖

mat -a clas UC ++ 需要 turn gpo open

題目大意

?  給你一個\(n\times m\)的地圖,每個格子上都有一顆植物,有的植物能保護其他植物。僵屍從右往左進攻,每吃掉一顆植物就可以得到\(a_{i,j}\)的收益(\(a_{i,j}\)可以是負數)。求僵屍的最大收益

?  \(1\leq n\leq20,1\leq m\leq30\)

題解

?  這種一個東西可以保護另一個東西而且數據範圍那麽小的題目顯然是最大權閉合子圖。

?  僵屍從右往左進攻,所以一棵植物可以保護它左邊的植物。

?  如果保護關系形成一個環,就都不能選。

?  直接套模板即可。

?  可能需要一些優化

代碼

#include<cstdio>
#include<cstring>
#include<algorithm> #include<cstdlib> #include<ctime> #include<utility> #include<queue> using namespace std; typedef long long ll; typedef pair<int,int> pii; struct list { int v[1000010]; int w[1000010]; int t[1000010]; int h[1010]; int n; list() { memset(h,0
,sizeof h); n=0; } void add(int x,int y,int z) { n++; v[n]=y; w[n]=z; t[n]=h[x]; h[x]=n; } }; list l,l2; void add(int x,int y,int z) { l.add(x,y,z); l.add(y,x,0); } int n,m; int w[110][110]; int gx[1010]; int gy[1010]; int id(int x,int y) { return
(x-1)*m+y; } int vis[1010]; int b[1010]; void dfs(int x) { vis[x]=1; int i; for(i=l2.h[x];i;i=l2.t[i]) { if(!vis[l2.v[i]]) dfs(l2.v[i]); if(b[l2.v[i]]||vis[l2.v[i]]==1) { // w[gx[x]][gy[x]]=-10000000; b[x]=1; } } vis[x]=2; } int d[1010]; int S,T; int c[30][40][30][40]; int bfs() { memset(d,-1,sizeof d); queue<int> q; q.push(S); d[S]=0; int x,i; while(!q.empty()) { x=q.front(); q.pop(); for(i=l.h[x];i;i=l.t[i]) if(l.w[i]&&d[l.v[i]]==-1) { d[l.v[i]]=d[x]+1; if(l.v[i]==T) return 1; q.push(l.v[i]); } } return 0; } int op(int x) { return ((x-1)^1)+1; } int dfs(int x,int flow) { if(x==T) return flow; int c,s=0,i; for(i=l.h[x];i;i=l.t[i]) if(l.w[i]&&d[l.v[i]]==d[x]+1) { c=dfs(l.v[i],min(flow,l.w[i])); s+=c; flow-=c; l.w[i]-=c; l.w[op(i)]+=c; if(!flow) break; } if(flow) d[x]=-1; return s; } int main() { memset(b,0,sizeof b); memset(c,0,sizeof c); // freopen("bzoj1565.in","r",stdin); // freopen("bzoj1565.out","w",stdout); scanf("%d%d",&n,&m); S=n*m+1; T=S+1; int sum=0; int i,j,k,o,x,y,u; for(i=1;i<=n;i++) for(j=1;j<=m;j++) { scanf("%d",&w[i][j]); gx[id(i,j)]=i; gy[id(i,j)]=j; scanf("%d",&u); for(k=1;k<=u;k++) { scanf("%d%d",&x,&y); x++; y++; c[i][j][x][y]=1; } if(j>1) c[i][j][i][j-1]=1; for(x=1;x<=n;x++) for(y=1;y<=m;y++) if(c[i][j][x][y]) l2.add(id(x,y),id(i,j),0); } memset(vis,0,sizeof vis); for(i=1;i<=n;i++) for(j=1;j<=m;j++) if(!vis[id(i,j)]) dfs(id(i,j)); for(i=1;i<=n;i++) for(j=1;j<=m;j++) if(!b[id(i,j)]) { if(w[i][j]>0) { sum+=w[i][j]; add(S,id(i,j),w[i][j]); } else add(id(i,j),T,-w[i][j]); for(x=1;x<=n;x++) for(y=1;y<=m;y++) if(c[i][j][x][y]) if(!b[id(x,y)]) add(id(x,y),id(i,j),0x7fffffff); } int ans=0; while(bfs()) ans+=dfs(S,0x7fffffff); printf("%d\n",sum-ans); return 0; }

【BZOJ1565】【NOI2009】植物大戰僵屍 網絡流 最大權閉合子圖