Pleasant sheep and big big wolf
题目:在一个N * M 的矩阵草原上,分布着羊和狼。每一个格子仅仅能存在0或1仅仅动物。如今要用栅栏将全部的狼和羊分开。问怎么放,栅栏数放的最少,求出个数?
解析:将狼群看作一个集合,羊群看作一个集合。然后设置源点和汇点,将两点至存在动物的点的距离赋值为1,构图,因为求得是栅栏数,从存在动物的位置向四周发散点赋值为1,即该方向放置一个栅栏。然后能够发现变成了求最小割,即求出最大流。须要注意的是,因为数据比較大,200 * 200。假设设置源点和汇点相差较大(即s = 0,e = n * m ),easyTLE.
#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的更多相关文章
- HDU 3046 Pleasant sheep and big big wolf(最小割)
HDU 3046 Pleasant sheep and big big wolf 题目链接 题意:一个n * m平面上,1是羊.2是狼,问最少要多少围墙才干把狼所有围住,每有到达羊的路径 思路:有羊和 ...
- 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 ...
- 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 ...
- 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 a ...
- HDU 3046 Pleasant sheep and big wolf(最小割最大流+Dinic)
http://acm.hdu.edu.cn/showproblem.php?pid=3046 题意: 给出矩阵地图和羊和狼的位置,求至少需要建多少栅栏,使得狼不能到达羊. 思路:狼和羊不能到达,最小割 ...
- hdu-3046-Pleasant sheep and big big wolf(最大流最小割)
题意: 给出最少栏杆数使狼和羊分离 分析: 将狼与源点连,羊与汇点连,容量都为无穷,将图的各个相邻点连接,容量为1 然后题目就转化成最小去掉多少条边使不连通,即求最小割最大流. // File Nam ...
- HDU 3046Pleasant sheep and big big wolf(切最小网络流)
职务地址:HDU 3046 最小割第一发!事实上也没什么发不发的. ..最小割==最大流.. 入门题,可是第一次入手最小割连入门题都全然没思路... sad..对最小割的本质还是了解的不太清楚.. 这 ...
- HDU3046_Pleasant sheep and big big wolf
给一个n*m的数字阵,1表示羊的位置,2表示狼的位置,0表示没有东西,可以通过.在每个格子的4边都可以建立围栏,有围栏的话狼是不能通过的. 现在求最少建立多少围栏能够保证狼无法接触到羊. 题目的模型很 ...
- 【转载】图论 500题——主要为hdu/poj/zoj
转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并 ...
随机推荐
- Vue框架Element UI教程-axios请求数据
Element UI手册:https://cloud.tencent.com/developer/doc/1270 中文文档:http://element-cn.eleme.io/#/zh-CN gi ...
- freemark实现遍历 list,每行三个
我的做法是先做一个模板,这三个只都是从list里取出来的 在后台将每三个值放到一个map里 List<Map<String, Object>> newsList=new Arr ...
- POJ 1721
好像不需要用到开方什么的... 可以知道,一副牌即是一个循环,那么,由于GCD(L,K)=1,所以一次洗牌后,亦是一个循环.其实,K次洗牌等于是T^(2^K)了.既然是循环,必定有周期.那么,周期是多 ...
- java 基础概念 -- 数组与内存控制
问题1: Java在声明数组的过程中,是怎样分配内存的? 在栈内存中 建一个数组变量,再在堆内存中 建一个 数组对象.至于详细的内存分配细节,还得看 该初始化是 数组动态初始化 还是 数组静态初始化. ...
- Bmob移动后端云服务平台--Android从零開始--(二)android高速入门
Bmob移动后端云服务平台--Android从零開始--(二)android高速入门 上一篇博文我们简介何为Bmob移动后端服务平台,以及其相关功能和优势. 本文将利用Bmob高速实现简单样例,进一步 ...
- oracle实现自增id
--oracle实现自增id --创建一张T_StudentInfo表 create table T_StudentInfo ( "id" integer not null pri ...
- zzulioj--1708--01串也疯狂之光棍也有伴(dp)
1708: 01串也疯狂之光棍也有伴 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 199 Solved: 50 SubmitStatusWeb B ...
- 关于markdown的使用
首先: https://www.cnblogs.com/jordangong/p/9804777.html 注意:提交博客时需将 Markdown 源码粘贴到编辑器中,且编辑器没有实时预览,可以上传后 ...
- POJ 1064 Cable master (二分答案,G++不过,C++就过了)
题目: 这题有点坑,G++过不了,C++能过. 条件:n个数据a[],分成k段,结果精度要求两位小数. 问题:每段最长为多少? 思路:因为精度要求为两位小数,我先把所有的长度a[]*100. 我们对答 ...
- 《Unix环境高级编程》读书笔记 第3章-文件I/O
1. 引言 Unix系统的大多数文件I/O只需用到5个函数:open.read.write.lseek以及close 本章描述的函数经常被称为不带缓冲的I/O.术语不带缓冲指的是在用户的进程中对其不会 ...