博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 3046【最小割】
阅读量:4979 次
发布时间:2019-06-12

本文共 3084 字,大约阅读时间需要 10 分钟。

题目大意:在一个n*m的矩阵上,1代表羊,2代表狼,0代表平地,我们有长度为1的一个栅栏(不是放在格子上的,是放在格子和格子之间的空隙上的),问使用最少的栅栏,能够使得狼吃不到羊。

又学到了一招,以前一直以为建图是要先设好S点T点,在把其他的点和他们两一一相连。今天学到了原来可以在整个map上根据条件建好图,再把其中的某些目标点和源汇点相连的。

思路如下:

1、建立最小割模型:

①建立源点S,将源点S连入各个有狼的节点上,权值设定为INF,表示狼可以从任意方向出发。
②建立汇点T,将各个羊节点连入汇点T,权值设定为INF。
③将每两个相邻的格子之间建立一条边,权值设定为1,表示如果拆掉了这条边,这条边就不能走了

#include
#include
#include
#include
#define MAX 400000#define INF 0x1f1f1f1fusing namespace std;int map[210][210];int ss, tt;int n, m;int cont;int head[MAX];int d[4][2] = { {0,1},{0,-1},{-1,0},{1,0} };int divv[MAX];int cur[MAX];struct edge { int from, to, w, next;}e[MAX];void add(int u, int v, int w) { e[cont].from = u; e[cont].to = v; e[cont].w = w; e[cont].next = head[u]; head[u] = cont++;}int makediv() { memset(divv, 0, sizeof(divv)); divv[ss] = 1; queue
Q; Q.push(ss); while (!Q.empty()) { int u = Q.front(); if (u == tt) return 1; Q.pop(); for (int i = head[u]; i != -1; i = e[i].next) { int w = e[i].w; int v = e[i].to; if (divv[v] == 0 && w) { divv[v] = divv[u] + 1; Q.push(v); } } } return 0;}int DFS(int u, int maxflow, int tt) { if (u == tt) return maxflow; int ret = 0; for (int &i = cur[u]; i != -1; i = e[i].next) { int v = e[i].to; int w = e[i].w; if (divv[v] == divv[u] + 1 && w) { int f = DFS(v, min(maxflow - ret, w), tt); e[i].w -= f; e[i ^ 1].w += f; ret += f; if (ret == maxflow) return ret; } } return ret;}int kase = 0;void Dinic() { int ans = 0; while (makediv() == 1) { memcpy(cur, head, sizeof(head)); ans += DFS(ss, INF, tt); } printf("Case %d:\n%d\n", ++kase, ans);}int main(void) { kase = 0; while (~scanf("%d%d", &n, &m)) { memset(head, -1, sizeof(head)); cont = 0; ss = 0; tt = n * m + 1; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { scanf("%d", &map[i][j]); if (map[i][j] == 2) { //每只狼都可以从任意方向出发 add(ss, (i - 1)*m + j, INF); add((i - 1)*m + j, ss, 0); } if (map[i][j] == 1) { add((i - 1)*m + j, tt, INF); add(tt, (i - 1)*m + j, 0); } } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { for (int t = 0; t < 4; t++) { int xx = i + d[t][0]; int yy = j + d[t][1]; if (xx > 0 && xx <= n && yy > 0 && yy <= m) { add((i - 1)*m + j, (xx - 1)*m + yy, 1); add((xx - 1)*m + yy, (i - 1)*m + j, 0); } } } } Dinic(); } return 0;}

转载于:https://www.cnblogs.com/tennant/p/8977023.html

你可能感兴趣的文章
sql 查看数据库环境及一些参数
查看>>
u-boot分析与移植——基于u-boot-2011.3和FL2440
查看>>
OSX10.10 Yosemite安装Metasploit
查看>>
MyBatis知多少(4)MyBatis的优势
查看>>
添加Service Reference, 无法为服务生成代码错误的解决办法
查看>>
C语言基础(17)-作用域
查看>>
Python函数式编程指南(三):迭代器
查看>>
aix的lvm管理
查看>>
《深入理解Android 卷1》笔记
查看>>
jQuery----blur()方法
查看>>
FFmpeg命令详解
查看>>
`ln`命令创建软链接错误
查看>>
mysqlDOS命令
查看>>
jquery $(document).ready() 与window.onload的区别
查看>>
day13_自动抽取数据——监控存储过程
查看>>
[转]http返回头中content-length与Transfer-Encoding: chunked的问题释疑
查看>>
display:table / display:table-cell 用法
查看>>
UITableView优化
查看>>
iOS 点击事件传递及响应
查看>>
谷歌应用商城打开
查看>>