博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 1412 最小割
阅读量:5236 次
发布时间:2019-06-14

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

思路:一个篱笆的作用就是堵死一条路,我们将S与狼建边,权值为inf, 将羊与T建边,权值为inf, 每个点与其可以到的路建边,权值为1,

然后跑最小割,因为如果S到T有通路说明狼肯定可以到羊,每一个割代表一个篱笆。

#include
#define LL long long#define fi first#define se second#define mk make_pair#define pii pair
using namespace std;const int N = 2e4 + 7;const int M = 2e5 + 7;const int inf = 0x3f3f3f3f;const LL INF = 0x3f3f3f3f3f3f3f3f;const int mod = 1e9 + 7;int n, m, S, T, tot, level[N], head[N], a[101][101], id[101][101];int dx[] = {
0, 0, 1, -1}, dy[] = {
1, -1, 0, 0};struct Edge { int to, w, nx;}edge[M << 1];void add(int u, int v, int w) { edge[tot].to = v; edge[tot].w = w; edge[tot].nx = head[u]; head[u] = tot++; edge[tot].to = u; edge[tot].w = 0; edge[tot].nx = head[v]; head[v] = tot++;}bool bfs() { memset(level, 0, sizeof(level)); queue
que; que.push(S), level[S] = 1; while(!que.empty()) { int u = que.front(); que.pop(); if(u == T) return true; for(int i = head[u]; ~i; i = edge[i].nx) { int v = edge[i].to, w = edge[i].w; if(level[v] || w <= 0) continue; level[v] = level[u] + 1; que.push(v); } } return false;}int dfs(int u, int p) { if(u == T) return p; int ret = 0; for(int i = head[u]; ~i; i = edge[i].nx) { int v = edge[i].to, w = edge[i].w; if(level[v] != level[u] + 1 || w <= 0) continue; int f = dfs(v, min(p - ret, w)); ret += f; edge[i].w -= f; edge[i ^ 1].w += f; if(ret == p) break; } if(!ret) level[u] = 1; return ret;}int Dinic() { int ans = 0; while(bfs()) ans += dfs(S, inf); return ans;}void init() { tot = 0; memset(head, -1, sizeof(head));}bool check(int x, int y) { if(x < 1 || x > n) return false; if(y < 1 || y > m) return false; return true;}int main() { init(); scanf("%d%d", &n, &m); S = 0, T = n * m + 1; for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { scanf("%d", &a[i][j]); id[i][j] = (i - 1) * m + j; if(a[i][j] == 1) add(S, id[i][j], inf); else if(a[i][j] == 2) add(id[i][j], T, inf); } } for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { for(int k = 0; k < 4; k++) { int x = i + dx[k], y = j + dy[k]; if(check(x, y) && (a[i][j] != a[x][y] || !a[i][j] && !a[x][y])) { add(id[i][j], id[x][y], 1); } } } } printf("%d\n", Dinic()); return 0;}/**/

 

转载于:https://www.cnblogs.com/CJLHY/p/9276464.html

你可能感兴趣的文章
nopCommerce如何支持MySQL
查看>>
VS代码管理插件AnkhSvn
查看>>
VS代码注释插件GhostDoc
查看>>
add printer driver error 1802修复说明
查看>>
LAMP环境
查看>>
如何添加ORACLE 的 ODBC
查看>>
Python深层拷贝
查看>>
判断当前线程是否是在主线程中
查看>>
【php增删改查实例】第十三节 - EasyUI列格式化
查看>>
微信公众号开发java版-消息回复(普通文字消息和语音消息)
查看>>
2018九月刷题列表
查看>>
Jquery简单动画的实现记录
查看>>
栈的实现原理
查看>>
Day 35 协程
查看>>
如何为EXCEL单元格颜色排序
查看>>
Hat's Words
查看>>
Oracle字符函数
查看>>
git介绍和常用指令
查看>>
在SQL Server中将数据导出为XML和Json
查看>>
Etcd源码解析(转)
查看>>