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
Case 1: 4
题意:在一个n*m的草原上,羊是1,狼是2,要安长度为1的栅栏,要求用最小的栅栏保证羊不被狼吃掉。
思路:建立一个超级源点与狼相连,长度为inf,建立一个超级汇点与羊相连,长度为inf,然后剩下的格子相连长度为1,然后找。
这个图真心怪怪的,一开始用搜索找四个方向,愣是不对,最后只好用笨办法,一个一个来喽。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <set>
#include <queue>
#include <map>
using namespace std;
const int inf=0x3f3f3f3f;
int head[1000100],num[100010],d[100010],pre[100010],cur[100010],mp[310][310];
int n,m,cnt,nv,s,t;
int jx[]={1,0,-1,0};
int jy[]={0,1,0,-1};
struct node
{
int u,v,cap;
int next;
}edge[10000010];
void add(int u, int v, int cap)
{
edge[cnt].v=v;
edge[cnt].cap=cap;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].v=u;
edge[cnt].cap=0;
edge[cnt].next=head[v];
head[v]=cnt++;
}
void bfs()
{
memset(d,-1,sizeof(d));
memset(num,0,sizeof(num));
queue<int >q;
q.push(t);
d[t]=0;
num[0]=1;
while(!q.empty()) {
int i;
int u=q.front();
q.pop();
for(i=head[u]; i!=-1; i=edge[i].next) {
int v=edge[i].v;
if(d[v]==-1) continue;
d[v]=d[u]+1;
num[d[v]]++;
q.push(v);
}
}
}
void isap()
{
memcpy(cur,head,sizeof(cur));
int flow=0, u=pre[s]=s, i;
bfs();
while(d[s]<nv) {
if(u==t) {
int f=inf, pos;
for(i=s; i!=t; i=edge[cur[i]].v) {
if(f>edge[cur[i]].cap) {
f=edge[cur[i]].cap;
pos=i;
}
}
for(i=s; i!=t; i=edge[cur[i]].v) {
edge[cur[i]].cap-=f;
edge[cur[i]^1].cap+=f;
}
flow+=f;
u=pos;
}
for(i=cur[u]; i!=-1; i=edge[i].next) {
if(d[edge[i].v]+1==d[u]&&edge[i].cap)
break;
}
if(i!=-1) {
cur[u]=i;
pre[edge[i].v]=u;
u=edge[i].v;
} else {
if(--num[d[u]]==0) break;
int mind=nv;
for(i=head[u]; i!=-1; i=edge[i].next) {
if(mind>d[edge[i].v]&&edge[i].cap) {
mind=d[edge[i].v];
cur[u]=i;
}
}
d[u]=mind+1;
num[d[u]]++;
u=pre[u];
}
}
printf("%d\n",flow);
}
int main()
{
int i, j,k;
int tt=1;
while(~scanf("%d%d",&n,&m))
{
cnt=0;
s=0;
t=n*m+1;
nv=t+1;
memset(head,-1,sizeof(head));
for(i=1; i<=n; i++)
{
for(j=1; j<=m; j++)
{
scanf("%d",&mp[i][j]);
if(mp[i][j]==1)
add(s,(i-1)*m+j,inf);
if(mp[i][j]==2)
add((i-1)*m+j,t,inf);
if(i!=1)
add((i-1)*m+j,(i-2)*m+j,1);// 与上面的点相连
if(i!=n)
add((i-1)*m+j,i*m+j,1);//与下面的点相连
if(j!=1)
add((i-1)*m+j,(i-1)*m+j-1,1);//与左边的点相连
if(j!=m)
add((i-1)*m+j,(i-1)*m+j+1,1);//与右边的点相连
}
}
printf("Case %d:\n",tt++);
isap();
}
return 0;
}
HDU 3046-Pleasant sheep and big big wolf(网络流_最小割)
原文:http://blog.csdn.net/u013486414/article/details/43196287