Pleasant sheep and big big wolf

点击打开链接

题目:在一个N * M 的矩阵草原上,分布着羊和狼,每个格子只能存在0或1只动物。现在要用栅栏将所有的狼和羊分开,问怎么放,栅栏数放的最少,求出个数?

解析:将狼群看作一个集合,羊群看作一个集合。然后设置源点和汇点,将两点至存在动物的点的距离赋值为1,构图,由于求得是栅栏数,从存在动物的位置向四周发散点赋值为1,即该方向放置一个栅栏。然后可以发现变成了求最小割,即求出最大流。需要注意的是,由于数据比较大,200 * 200。如果设置源点和汇点相差较大(即s = 0,e = n * m ),容易TLE.

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

// 最大流  ISAP + bfs+栈优化

const int maxn = 100010; //点的个数
const int maxm = 400010; //边的个数
const int INF = 0xfffffff;

struct Edge{
	int to, next, cap, flow;
}edge[ maxm ];//注意是maxm

int tol;
int head[ maxn ];
int gap[ maxn ], dep[ maxn ], cur[ maxn ];

void init(){
	tol = 0;
	memset( head, -1, sizeof( head ) );
}

void addedge( int u, int v, int w, int rw = 0 ){
	edge[ tol ].to = v; edge[ tol ].cap = w; edge[ tol ].flow = 0;
	edge[ tol ].next = head[ u ]; head[ u ] = tol++;
	edge[ tol ].to = u; edge[ tol ].cap = rw; edge[ tol ].flow = 0;
	edge[ tol ].next = head[ v ]; head[ v ] = tol++;
}

int Q[ maxn ];

void BFS( int start, int end ){
	memset( dep, -1, sizeof( dep ) );
	memset( gap, 0, sizeof( gap ) );
	gap[ 0 ] = 1;
	int front = 0, rear = 0;
	dep[ end ] = 0;
	Q[ rear++ ] = end;
	while( front != rear ){
		int u = Q[ front++ ];
		for( int i = head[ u ]; i != -1; i = edge[ i ].next ){
			int v = edge[ i ].to;
			if( dep[ v ] != -1 )
				continue;
			Q[ rear++ ] = v;
			dep[ v ] = dep[ u ] + 1;
			gap[ dep[ v ] ]++;
		}
	}
}

int S[ maxn ];
int sap( int start, int end, int N ){
	BFS( start, end );
	memcpy( cur, head, sizeof( head ) );
	int top = 0;
	int u = start;
	int ans = 0;
	while( dep[ start ] < N ){
		if( u == end ){
			int Min = INF;
			int inser;
			for( int i = 0; i < top; ++i ){
				if( Min > edge[ S[ i ] ].cap - edge[ S[ i ] ].flow ){
					Min = edge[ S[ i ] ].cap - edge[ S[ i ] ].flow;
					inser = i;
				}
			}
			for( int i = 0; i < top; ++i ){
				edge[ S[ i ] ].flow += Min;
				edge[ S[ i ] ^ 1 ].flow -= Min;
			}
			ans += Min;
			top = inser;
			u = edge[ S[ top ] ^ 1 ].to;
			continue;
		}
		bool flag = false;
		int v;
		for( int i = cur[ u ]; i != -1; i = edge[ i ].next ){
			v = edge[ i ].to;
			if( edge[ i ].cap - edge[ i ].flow && dep[ v ] + 1 == dep[ u ] ){
				flag = true;
				cur[ u ] = i;
				break;
			}
		}
		if( flag ){
			S[ top++ ] = cur[ u ];
			u = v;
			continue;
		}
		int Min = N;
		for( int i = head[ u ]; i != -1; i = edge[ i ].next ){
			if( edge[ i ].cap - edge[ i ].flow && dep[ edge[ i ].to ] < Min ){
				Min = dep[ edge[ i ].to ];
				cur[ u ] = i;
			}
		}
		gap[ dep[ u ] ]--;
		if( !gap[ dep[ u ] ] )
			return ans;
		dep[ u ] = Min + 1;
		gap[ dep[ u ] ]++;
		if( u != start )
			u = edge[ S[ --top ] ^ 1 ].to;
	}
	return ans;
}

int dir[ ][ 2 ] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };

int main(){
	int N, M, Case = 1;
	while( scanf( "%d%d", &N, &M ) != EOF ){
		int s = N * M, t = N * M + 1;
		int n = N * M + 2, temp;
		init();
		for( int i = 0; i < N; ++i ){
			for( int j = 0; j < M; ++j ){
				scanf( "%d", &temp );
				if( temp == 2 ){
					addedge( s, M * i + j, INF );
				}
				if( temp == 1 ){
					addedge( M * i + j, t, INF );
				}
				for( int k = 0; k < 4; ++k ){
					int x = i + dir[ k ][ 0 ];
					int y = j + dir[ k ][ 1 ];
					if( x >= 0 && x < N && y >= 0 && y < M )
						addedge( M * i + j, M * x + y,  1 );
				}
			}
		}
		printf( "Case %d:\n%d\n", Case++, sap( s, t, n ) );
	}
	return 0;
}

Pleasant sheep and big big wolf,布布扣,bubuko.com

时间: 2024-10-21 19:34:18

Pleasant sheep and big big wolf的相关文章

HDU 3046 Pleasant sheep and big big wolf

Pleasant sheep and big big wolf Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 304664-bit integer IO format: %I64d      Java class name: Main In ZJNU, there is a well-known prairie. And it attracts pleasant

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

HDU 3046 Pleasant sheep and big big wolf 题目链接 题意:一个n * m平面上,1是羊,2是狼,问最少要多少围墙才能把狼全部围住,每有到达羊的路径 思路:有羊和狼,要分成两个集合互不可达,显然的最小割,建图源点连狼,容量无穷,羊连汇点,容量无穷,然后相邻格子连边,容量为1 代码: #include <cstdio> #include <cstring> #include <queue> #include <algorithm

Pleasant sheep and big big wolf (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): 2371    Accepted Submission(s): 988 Problem Description In ZJNU, there is a well-known prairie. And it attracts p

hdoj 3046 Pleasant sheep and big big wolf 【最小割】

Pleasant sheep and big big wolf Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2570    Accepted Submission(s): 1056 Problem Description In ZJNU, there is a well-known prairie. And it attracts

hdu 3046 Pleasant sheep and big big wolf 最小割

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3046 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 A

HDU 3046-Pleasant sheep and big big wolf(网络流_最小割)

Pleasant sheep and big big wolf Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2254    Accepted Submission(s): 946 Problem Description In ZJNU, there is a well-known prairie. And it attracts p

hdoj--3046--Pleasant sheep and big big wolf(最小割经典)

 Pleasant sheep and big big wolf Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2699    Accepted Submission(s): 1114 Problem Description In ZJNU, there is a well-known prairie. And it attrac

HDU 3046Pleasant sheep and big big wolf(网络流之最小割)

题目地址:HDU 3046 最小割第一发!其实也没什么发不发的...最小割==最大流.. 入门题,但是第一次入手最小割连入门题都完全没思路...sad..对最小割的本质还是了解的不太清楚.. 这题就是对每两个相邻的格子的边界都要进行加边,然后求最大流就OK了. RE了好长时间,注意遍历加边的时候要从1开始,而不是0开始,因为0是源点的...(也许只有我才犯这种错误吧...)建图不多说了..只要了解了最小割,建图还是很容易想的. 代码如下: #include <iostream> #includ

HDU3046_Pleasant sheep and big big wolf

给一个n*m的数字阵,1表示羊的位置,2表示狼的位置,0表示没有东西,可以通过.在每个格子的4边都可以建立围栏,有围栏的话狼是不能通过的. 现在求最少建立多少围栏能够保证狼无法接触到羊. 题目的模型很简单,直接建立一个超级源点和超级汇点,狼连接远点流量无穷大,羊连接汇点流量无穷大,每个格子和四周的四个格子建立一条流量为1的边,要把狼羊分离就是求最小割了,最大流等于最小割,圆满解决问题. 召唤代码君: #include <iostream> #include <cstdio> #in