【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=1412
【题意】
在一个n*m的格子中,将羊和狼隔开的最小代价。
【思路】
最小割。
由S向狼连边inf,由羊向T连边inf,由狼向空格和羊连边1,由空格向四周连边为1,跑一遍最小割。
【代码】
1 #include<cmath> 2 #include<queue> 3 #include<vector> 4 #include<cstdio> 5 #include<cstring> 6 #include<iostream> 7 #include<algorithm> 8 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 9 using namespace std; 10 11 const int N = 1e4+10; 12 const int inf = 1e9; 13 const int dx[]={0,0,1,-1}; 14 const int dy[]={1,-1,0,0}; 15 16 struct Edge{ int u,v,cap,flow; 17 }; 18 struct Dinic { 19 int n,m,s,t; 20 int d[N],cur[N],vis[N]; 21 vector<Edge> es; 22 vector<int> g[N]; 23 queue<int> q; 24 void init(int n) { 25 this->n=n; 26 es.clear(); 27 for(int i=0;i<=n;i++) g[i].clear(); 28 } 29 void AddEdge(int u,int v,int w) { 30 es.push_back((Edge){u,v,w,0}); 31 es.push_back((Edge){v,u,0,0}); 32 m=es.size(); 33 g[u].push_back(m-2), 34 g[v].push_back(m-1); 35 } 36 bool bfs() { 37 memset(vis,0,sizeof(vis)); 38 q.push(s); d[s]=0; vis[s]=1; 39 while(!q.empty()) { 40 int u=q.front(); q.pop(); 41 for(int i=0;i<g[u].size();i++) { 42 Edge& e=es[g[u][i]]; 43 int v=e.v; 44 if(!vis[v] && e.cap>e.flow) { 45 d[v]=d[u]+1; 46 vis[v]=1; 47 q.push(v); 48 } 49 } 50 } 51 return vis[t]; 52 } 53 int dfs(int u,int a) { 54 if(u==t || a==0) return a; 55 int flow=0,f; 56 for(int& i=cur[u];i<g[u].size();i++) { 57 Edge& e=es[g[u][i]]; 58 int v=e.v; 59 if(d[v]==d[u]+1 && (f=dfs(v,min(a,e.cap-e.flow)))>0) { 60 e.flow+=f; 61 es[g[u][i]^1].flow-=f; 62 flow+=f; a-=f; 63 if(!a) break; 64 } 65 } 66 return flow; 67 } 68 int MaxFlow(int s,int t) { 69 this->s=s,this->t=t; 70 int flow=0; 71 while(bfs()) { 72 memset(cur,0,sizeof(cur)); 73 flow+=dfs(s,inf); 74 } 75 return flow; 76 } 77 } dc; 78 79 int n,m; 80 int mp[105][105]; 81 82 bool inside(int x,int y) 83 { 84 return x>=1&&x<=n&&y>=1&&y<=m; 85 } 86 87 int main() 88 { 89 scanf("%d%d",&n,&m); 90 dc.init(n*m+3); 91 int s=0,t=n*m+1; 92 FOR(i,1,n) FOR(j,1,m) scanf("%d",&mp[i][j]); 93 FOR(i,1,n) FOR(j,1,m) { 94 if(mp[i][j]==1) dc.AddEdge(s,(i-1)*m+j,inf); 95 else if(mp[i][j]==2) dc.AddEdge((i-1)*m+j,t,inf); 96 int x=i,y=j; 97 if(mp[x][y]==2) continue; 98 FOR(k,0,3) { 99 int nowx=x+dx[k],nowy=y+dy[k]; 100 if(!inside(nowx,nowy)) continue; 101 if(mp[x][y]!=1||mp[nowx][nowy]!=1) 102 dc.AddEdge((x-1)*m+y,(nowx-1)*m+nowy,1); 103 } 104 } 105 printf("%d ",dc.MaxFlow(s,t)); 106 return 0; 107 }