BZOJ 1412 [ZJOI2009]狼和羊的故事(最小割)
生活随笔
收集整理的這篇文章主要介紹了
BZOJ 1412 [ZJOI2009]狼和羊的故事(最小割)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?
【題目鏈接】?http://www.lydsy.com/JudgeOnline/problem.php?id=1412
?
【題目大意】
給出一塊地圖,1表示狼的領地,2表示羊的領地,0表示其余動物的領地,
現在要求在格子的交界修籬笆使得羊狼的領地不能互通,求最短的籬笆長度
?
【題解】
我們將每個格子之間連流量為1的邊,狼和源點連流量為INF的邊,
羊和匯點連流量為INF的邊,求此圖的最小割,就是籬笆的最短修補。
思路其實很簡單,使得圖被劃分為兩個部分,羊狼分離,因此就是最小割。
求出最大流的值,就是答案了。
?
【代碼】
#include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; const int INF=0x3f3f3f3f; const int MAX_V=20010; struct edge{int to,cap,rev;}; vector<edge> G[MAX_V]; int level[MAX_V],iter[MAX_V]; void add_edge(int from,int to,int cap){G[from].push_back((edge){to,cap,G[to].size()});G[to].push_back((edge){from,0,G[from].size()-1}); } void bfs(int s){memset(level,-1,sizeof(level));queue<int> que;level[s]=0;que.push(s);while(!que.empty()){int v=que.front(); que.pop();for(int i=0;i<G[v].size();i++){edge &e=G[v][i];if(e.cap>0&&level[e.to]<0){level[e.to]=level[v]+1;que.push(e.to);}}} } int dfs(int v,int t,int f){if(v==t)return f;for(int &i=iter[v];i<G[v].size();i++){edge &e=G[v][i];if(e.cap>0&&level[v]<level[e.to]){int d=dfs(e.to,t,min(f,e.cap));if(d>0){e.cap-=d;G[e.to][e.rev].cap+=d;return d;}}}return 0; } int max_flow(int s,int t){int flow=0;for(;;){bfs(s);if(level[t]<0)return flow;memset(iter,0,sizeof(iter));int f;while((f=dfs(s,t,INF))>0){flow+=f;}} } int n,m; int mp[110][110]; const int dx[]={1,-1,0,0},dy[]={0,0,1,-1}; bool check(int x,int y){return x<n&&x>=0&&y<m&&y>=0;} int main(){while(~scanf("%d%d",&n,&m)){int s=n*m,t=s+1;for(int i=0;i<=t;i++)G[i].clear();for(int i=0;i<n;i++)for(int j=0;j<m;j++){scanf("%d",&mp[i][j]);for(int k=0;k<4;k++){int x=i+dx[k],y=j+dy[k];if(check(x,y))add_edge(i*m+j,x*m+y,1);}if(mp[i][j]==1)add_edge(s,i*m+j,INF);if(mp[i][j]==2)add_edge(i*m+j,t,INF);}printf("%d\n",max_flow(s,t));}return 0; }轉載于:https://www.cnblogs.com/forever97/p/bzoj1412.html
總結
以上是生活随笔為你收集整理的BZOJ 1412 [ZJOI2009]狼和羊的故事(最小割)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DHAT:动态堆分析工具
- 下一篇: poj 2262 Goldbach's