题目
题解
这道题还挺简单的;要求割最小的边使狼和羊两个集合互不相交,一眼看出连边求最小割;
怎么建图呢?S向所有的羊,所有的狼向T,容量都是inf;在矩形中相邻的羊和狼连边,容量为1;
对于0的点怎么处理呢,我们把它默认为羊,羊向0, 0向狼连边即可容量均为1;
这么简单的题还没有1A,原来是我把0连向狼的边容量设为inf就WA了
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int maxn=100000;
const int inf=1e9;
int n,m,mp[101][101],maxflow;
struct Edge{
int next,to,dis;
}edge[maxn<<1];
int num_edge=-1,head[maxn],cur[maxn],deep[maxn];
int dx[5]={
0,0,0,1,-1},
dy[5]={
0,1,-1,0,0};
void add_edge(int from,int to,int dis)
{
edge[++num_edge].next=head[from];
edge[num_edge].to=to;
edge[num_edge].dis=dis;
head[from]=num_edge;
}
void add(int x,int y,int z) {add_edge(x,y,z); add_edge(y,x,0);}
int id(int x,int y) {
return (x-1)*m+y;}
queue <int> q;
bool bfs(int s,int t)
{
memset(deep,0x7f,sizeof(deep));
while (!q.empty()) q.pop();
for (int i=0; i<=t; i++) cur[i]=head[i];
deep[s]=0; q.push(s);
while (!q.empty())
{
int now=q.front(); q.pop();
for (int i=head[now]; i!=-1; i=edge[i].next)
{
int to=edge[i].to;
if (deep[to]>inf && edge[i].dis){
deep[to]=deep[now]+1;
q.push(to);
if (to==t) return 1;
}
}
}
return deep[t]<inf;
}
int dfs(int now,int t,int limit)
{
if (now==t || !limit) return limit;
int flow=0,f;
for (int i=cur[now]; i!=-1; i=edge[i].next)
{
cur[now]=i; int to=edge[i].to;
if (deep[to]==deep[now]+1 && (f=dfs(to,t,min(limit,edge[i].dis))))
{
flow+=f;
limit-=f;
edge[i].dis-=f;
edge[i^1].dis+=f;
if (!limit) break;
}
}
return flow;
}
void Dinic(int s,int t)
{
while (bfs(s,t))
maxflow+=dfs(s,t,inf);
}
void build()
{
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
{
if (mp[i][j]==1 || mp[i][j]==0)
for (int k=1; k<=4; k++)
{
int xx=i+dx[k]; int yy=j+dy[k];
if (1<=xx && xx<=n && 1<=yy && yy<=m)
if (mp[xx][yy]==2) add(id(i,j),id(xx,yy),1);
else if (mp[xx][yy]==0) add(id(i,j),id(xx,yy),1);
}
}
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
int S=0,T=n*m+1;
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
{
scanf("%d",&mp[i][j]);
if (mp[i][j]==1) add(S,id(i,j),inf);
else if (mp[i][j]==2) add(id(i,j),T,inf);
}
build();
// for (int i=0; i<=num_edge; i++) printf("%d: %d %d %d\n",i,edge[i^1].to,edge[i].to,edge[i].dis);
Dinic(S,T);
printf("%d",maxflow);
return 0;
}