[ZJOI2009]狼和羊的故事
阿新 • • 發佈:2017-09-29
inf vector 分開 char using style rom urn str
題目:BZOJ1412、洛谷P2598、Vijos P1555、codevs2351。
題目大意:有一個nm矩陣,每格裏住著狼、羊或其他動物。現在要你建最少的籬笆,使得狼和羊分開。問最少建多長的籬笆。
解題思路:網絡流最小割問題,求最大流即可。
首先建超級源點S=0,超級匯點T=nm+1。對於每只狼,從S到這只狼連接容量inf的邊;對於每只羊,從這只羊到T連接容量inf的邊。
然後,對於每個點,若該點不是羊,則從該點向它四個方向所有不是狼的點連接容量為1的邊。
建完圖後就是裸的最大流問題,用Dinic、ISAP等都可,EK應該也可。
我用的是Dinic。
C++ Code:
#include<stdio.h> #include<cctype> #include<vector> #include<algorithm> #include<cstring> #include<queue> using namespace std; #define INF 0x3f3f3f3f int n,m,level[30003],iter[30003],a[103][103]; struct edges{ int to,cap,rev; }; vector<edges>G[200003]; queue<int>q; inline int readint(){ int p=0; char c=getchar(); for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar())p=p*10+c-‘0‘; return p; } inline void addedge(int from,int to,int cap){ G[from].push_back((edges){to,cap,G[to].size()}); G[to].push_back((edges){from,0,G[from].size()-1}); } void bfs(int s){ memset(level,-1,sizeof(level)); level[s]=0; q.push(s); while(!q.empty()){ int u=q.front(); q.pop(); for(int i=0;i<G[u].size();++i){ edges& e=G[u][i]; if(level[e.to]<0&&e.cap>0){ level[e.to]=level[u]+1; q.push(e.to); } } } } int dfs(int u,int t,int f){ if(u==t)return f; for(int& i=iter[u];i<G[u].size();++i){ edges& e=G[u][i]; if(e.cap>0&&level[e.to]>level[u]){ int d=dfs(e.to,t,min(f,e.cap)); if(d){ e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0; } int max_flow(int s,int t){ int flow=0; while(1){ bfs(s); if(level[t]<0)return flow; memset(iter,0,sizeof(iter)); int f; while(f=dfs(s,t,INF))flow+=f; } } int main(){ memset(a,-1,sizeof a); n=readint(),m=readint(); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j)a[i][j]=readint(); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j){ if(a[i][j]==1)addedge(0,(i-1)*m+j,INF);else if(a[i][j]==2) addedge((i-1)*m+j,n*m+1,INF); if(a[i][j]==2)continue; if(a[i+1][j]==2||a[i+1][j]==0)addedge((i-1)*m+j,i*m+j,1); if(a[i-1][j]==2||a[i-1][j]==0)addedge((i-1)*m+j,(i-2)*m+j,1); if(a[i][j+1]==2||a[i][j+1]==0)addedge((i-1)*m+j,(i-1)*m+j+1,1); if(a[i][j-1]==2||a[i][j-1]==0)addedge((i-1)*m+j,(i-1)*m+j-1,1); } printf("%d\n",max_flow(0,n*m+1)); return 0; }
[ZJOI2009]狼和羊的故事