您的位置:首页 > 其它

【HDU - 3046】Pleasant sheep and big big wolf 【最大流-最小割】

2017-10-30 13:38 716 查看
In ZJNU, there is a well-known prairie. And it attracts pleasant sheep and his companions to have a holiday. Big big wolf and his families know about this, and quietly hid in the big lawn. As ZJNU ACM/ICPC team, we have an obligation to protect pleasant sheep and his companions to free from being disturbed by big big wolf. We decided to build a number of unit fence whose length is 1. Any wolf and sheep can not cross the fence. Of course, one grid can only contain an animal.

Now, we ask to place the minimum fences to let pleasant sheep and his Companions to free from being disturbed by big big wolf and his companions.



There are many cases.

For every case:

N and M(N,M<=200)

then N*M matrix:

0 is empty, and 1 is pleasant sheep and his companions, 2 is big big wolf and his companions.

Output

For every case:

First line output “Case p:”, p is the p-th case;

The second line is the answer.

Sample Input

4 6

1 0 0 1 0 0

0 1 1 0 0 0

2 0 0 0 0 0

0 2 0 1 1 0

Sample Output

Case 1:

4

题意 :n*m的矩阵中,如果点权为0,表示空地,1表示这个位置有一头羊,2表示这个位置有一头狼,现在我们相拥最少的篱笆数来防止所有的羊被狼吃掉。求最小的篱笆数。

分析: S与所有的羊连边INF,所有的狼和T连边INF(INF就是防止最小割隔断这些边,因为显然隔断这些边不合题意) 其他的边按照地图来连边容量为1,最后跑S到T 的最大流。

即最小割,因为容量都是1,所以最小割的容量就是数量,最小割的意义就是让从超级源点出发的所有流都无法到达超级汇点,同时隔断的容量最小(又因为我们将狼和羊的边也设为INF,所以所有的羊就和S相当于同一个超级源点,所有的狼和T相当于同一个汇点),这样不就是我们想要的用最少的篱笆来将羊和狼隔开。

代码实现很简单。

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define  LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)

const int MAXN =  80000+11;
const int MAXM =  5;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;

struct Edge {
int form,to,cap,flow,nexts;
}edge[MAXN*10];
int head[MAXN],top;
void init(){
memset(head,-1,sizeof(head));
top=0;
}
void addedge(int a,int b,int c){
Edge e={a,b,c,0,head[a]};
edge[top]=e;head[a]=top++;

Edge ee={b,a,0,0,head[b]};
edge[top]=ee;head[b]=top++;
}
int n,m;
int S,T;
int to[][2]={1,0,-1,0,0,1,0,-1};
int cnt;
void getmap(){
S=0,T=n*m+1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int val;scanf("%d",&val);
if(val==1)
addedge(S,(i-1)*m+j,inf);
else if(val==2) addedge((i-1)*m+j,T,inf);
for(int k=0;k<4;k++){
int nx=i+to[k][0];int ny=j+to[k][1];
if(nx<1||ny<1||nx>n||ny>m) continue;
addedge((i-1)*m+j,(nx-1)*m+ny,1);
}
}
}
}

int vis[MAXN],dis[MAXN];
int cur[MAXN];
bool bfs(int st,int ed){
queue<int>Q;
memset(vis,0,sizeof(vis));
memset(dis,-1,sizeof(dis));
Q.push(st);vis[st]=1;dis[st]=1;
while(!Q.empty()){
int now=Q.front();Q.pop();
for(int i=head[now];i!=-1;i=edge[i].nexts){
Edge e=edge[i];
if(!vis[e.to]&&e.cap-e.flow>0){
vis[e.to]=1;
dis[e.to]=dis[now]+1;
if(e.to==ed) return 1;
Q.push(e.to);
}
}
}
return 0;
}
int dfs(int now,int a,int ed){
if(a==0||now==ed) return a;
int flow=0,f;
for(int &i=cur[now];i!=-1;i=edge[i].nexts){
Edge &e=edge[i];
if(dis[e.to]==dis[now]+1&&(f=dfs(e.to,min(e.cap-e.flow,a),ed))>0){
e.flow+=f;
flow+=f;
edge[i^1].flow-=f;
a-=f;
if(a==0) break;
}
}
return flow;
}
int max_flow(int st ,int ed){
int flow=0;
while(bfs(st,ed)){
memcpy(cur,head,sizeof(head));
flow+=dfs(st,inf,ed);
}
return flow;
}
int main(){
//  fread();
//  fwrite();
int ncase=1;
while(scanf("%d%d",&n,&m)!=EOF){
init();
getmap();
int ans=max_flow(S,T);
printf("Case %d:\n%d\n",ncase++,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: