HDU 3046 Pleasant sheep and big big wolf(最小割-Dinic)

来源:互联网 发布:各国进出口数据 编辑:程序博客网 时间:2024/05/21 03:28

Description
有N*M的矩阵,每个非空格子都住着狼或羊其一,矩阵边缘已经装上篱笆。要求你在一些单位格子的边界上修建尽量短的篱笆,将狼和羊分隔开。问最小长度
Input
多组用例,每组用例第一行为两个整数N和M表示矩阵行列数,之后为以N*M的矩阵表示矩阵各点的状态,0表示空格,1表示有羊的格,2表示有狼的格,以文件尾结束输入
Output
对于每组用例,输出需要修建的最短篱笆数
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
Solution
将该N*M的矩阵看做N*M个点,若两格有公共边就连一条容量为1的无向边。源点向每只羊连边,每只狼向汇点连边,容量均为无穷大。该图的最小割即为最短篱笆的总长(连无穷:不能杀掉一只狼或者羊,不能割这个;相邻连1:将所有他们边界的删掉,就不连通)
Code

#include<cstdio>#include<iostream>#include<cstring>#include<queue>using namespace std;#define maxn 555555#define maxm 555555#define INF 0x3f3f3f3fint head[maxn],cur[maxn],d[maxn],st[maxm],s,e,no,n;struct point{    int u,v,flow,next;    point(){};    point(int x,int y,int z,int w):u(x),v(y),next(z),flow(w){};}p[maxm];void add(int x,int y,int z){    p[no]=point(x,y,head[x],z);     head[x]=no++;    p[no]=point(y,x,head[y],0);     head[y]=no++;}void init(){    memset(head,-1,sizeof(head));    no=0;}bool bfs(){    int i,x,y;    queue<int>q;    memset(d,-1,sizeof(d));    d[s]=0;     q.push(s);    while(!q.empty())    {        x=q.front();            q.pop();        for(i=head[x];i!=-1;i=p[i].next)        {            if(p[i].flow&& d[y = p[i].v]<0)            {                d[y]=d[x]+1;                if(y==e)                        return true;                q.push(y);            }        }    }    return false;}int dinic(){    int i,loc,top,x=s,nowflow,maxflow=0;    while(bfs()){        for(i=s;i<=e;i++)               cur[i]=head[i];        top=0;        while(true)        {            if(x==e)            {                nowflow=INF;                for(i=0;i<top;i++)                {                    if(nowflow>p[st[i]].flow)                    {                        nowflow=p[st[i]].flow;                        loc=i;                    }                }                for(i=0;i<top;i++)                {                    p[st[i]].flow-=nowflow;                    p[st[i]^1].flow+=nowflow;                }                maxflow+=nowflow;                top=loc;                    x=p[st[top]].u;            }            for(i=cur[x];i!=-1;i=p[i].next)                if(p[i].flow&&d[p[i].v]==d[x]+1)                     break;            cur[x]=i;            if(i!=-1)            {                st[top++]=i;                x=p[i].v;            }            else             {                if(!top)                        break;                d[x]=-1;                x=p[st[--top]].u;            }        }    }    return maxflow;}int N,M;int main(){    int res=1;    while(~scanf("%d%d",&N,&M))    {        init();//初始化         s=0;//源点为0         e=N*M+1;//汇点为N*M+1         n=N*M;        for(int i=1;i<=N;i++)            for(int j=1;j<=M;j++)            {                int x;                scanf("%d",&x);                int pos=(i-1)*M+j;                //和与该格有公共边的格建容量为1的边                 if(i>1)                    add(pos,pos-M,1);                if(j>1)                    add(pos,pos-1,1);                if(i<N)                    add(pos,pos+M,1);                if(j<M)                    add(pos,pos+1,1);                if(x==1)//源点与羊建容量为无穷的边                     add(s,pos,INF);                if(x==2)//狼与汇点建容量为无穷的边                     add(pos,e,INF);            }        printf("Case %d:\n",res++);//按格式输出         printf("%d\n",dinic());    }    return 0;}
1 0
原创粉丝点击