[bzoj1412][ZJOI2009]狼和羊的故事(最小割)

题目

传送门

题解

这道题还挺简单的;要求割最小的边使狼和羊两个集合互不相交,一眼看出连边求最小割;
怎么建图呢?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;
}

猜你喜欢

转载自blog.csdn.net/A_Comme_Amour/article/details/79681087