hdu 3046(最小割)

Pleasant sheep and big big wolf

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2794    Accepted Submission(s): 1150


Problem Description
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.
 

 

Input
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
 

 

Source
题意:给出一个n*m的矩阵,里面有一些狼(2)和一些羊(1),现在要将狼羊隔开,可以在两点之间建造围栏将狼隔在外面,问围栏的最小长度应该是多少?
题解:构图,将每个点与其边上的点连接起来,容量为1,这样的话割这条边就等于是建造了一个长度为1的围栏,然后建造一个超级源点和羊连起来,容量为INF,因为我们不能去割羊,狼与超级汇点同理.跑一遍最大流即为答案。
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int INF = 999999999;
const int N = 45005;
const int M = 1000005;
struct Edge{
    int v,w,next;
}edge[M];
int head[N];
int level[N];
int tot;
void init()
{
    memset(head,-1,sizeof(head));
    tot=0;
}
void addEdge(int u,int v,int w,int &k)
{
    edge[k].v = v,edge[k].w=w,edge[k].next=head[u],head[u]=k++;
    edge[k].v = u,edge[k].w=0,edge[k].next=head[v],head[v]=k++;
}
int BFS(int src,int des)
{
    queue<int>q;
    memset(level,0,sizeof(level));
    level[src]=1;
    q.push(src);
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        if(u==des) return 1;
        for(int k = head[u]; k!=-1; k=edge[k].next)
        {
            int v = edge[k].v;
            int w = edge[k].w;
            if(level[v]==0&&w!=0)
            {
                level[v]=level[u]+1;
                q.push(v);
            }
        }
    }
    return -1;
}
int dfs(int u,int des,int increaseRoad){
    if(u==des||increaseRoad==0) {
        return increaseRoad;
    }
    int ret=0;
    for(int k=head[u];k!=-1;k=edge[k].next){
        int v = edge[k].v,w=edge[k].w;
        if(level[v]==level[u]+1&&w!=0){
            int MIN = min(increaseRoad-ret,w);
            w = dfs(v,des,MIN);
            if(w > 0)
            {
                edge[k].w -=w;
                edge[k^1].w+=w;
                ret+=w;
                if(ret==increaseRoad){
                    return ret;
                }
            }
            else level[v] = -1;
            if(increaseRoad==0) break;
        }
    }
    if(ret==0) level[u]=-1;
    return ret;
}
int Dinic(int src,int des)
{
    int ans = 0;
    while(BFS(src,des)!=-1) ans+=dfs(src,des,INF);
    return ans;
}
int n,m;
int graph[250][250];
int P(int x,int y){
    return (x-1)*m+y;
}
int dir[][2] = {{1,0},{-1,0},{0,1},{0,-1}};
int main(){
    int t=  1;
    while(scanf("%d%d",&n,&m)!=EOF){
        init();
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&graph[i][j]);
            }
        }
        int src = 0,des = n*m+1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(graph[i][j]==1){
                    addEdge(src,P(i,j),INF,tot);
                }
                if(graph[i][j]==2){
                    addEdge(P(i,j),des,INF,tot);
                }
                for(int k=0;k<4;k++){
                    int x = i+dir[k][0],y = j+dir[k][1];
                    if(x>n||x<1||y>m||y<1) continue;
                    addEdge(P(i,j),P(x,y),1,tot);
                }
            }
        }
        int mincut = Dinic(src,des);
        printf("Case %d:\n",t++);
        printf("%d\n",mincut);
    }
}

 

posted @ 2016-08-04 10:08  樱花庄的龙之介大人  阅读(144)  评论(0编辑  收藏  举报