BZOJ 1458: 士兵占领( 网络流 )
2015-10-01 19:41
671 查看
![](https://oscdn.geek-share.com/Uploads/Images/Content/202004/02/2f131c62972f8e113be1bfae450c43e0.png)
先判无解
把整个棋盘都放上士兵, 只需求最多可以拿走多少个士兵即可.每一行看做一个点r(i), 每一列看做一个点c(i)
S->r(i), c(i)->T 连边, 容量为可以拿走的最大士兵数
(i,j)不是障碍格:r(i)->c(j),容量+oo
最后答案为n*m-k-maxflow
----------------------------------------------------------------------
#include<bits/stdc++.h>using namespace std;const int maxn = 209;const int INF = 10000000;struct edge { int to, cap; edge *next, *rev;} E[maxn * maxn << 1], *pt = E, *head[maxn];inline void add(int u, int v, int w) { pt->to = v; pt->cap = w; pt->next = head[u]; head[u] = pt++;}inline void addedge(int u, int v, int w) { add(u, v, w); add(v, u, 0); head[u]->rev = head[v]; head[v]->rev = head[u];}edge *p[maxn], *cur[maxn];int R[maxn], C[maxn], sumr[maxn], sumc[maxn], h[maxn], cnt[maxn], S, T, N;bool ok[maxn][maxn];int maxFlow() { memset(cnt, 0, sizeof cnt); memset(h, 0, sizeof h); cnt[0] = N; for(int i = 0; i < N; i++) cur[i] = head[i]; edge* e; int flow = 0; for(int x = S, A = INF; h[S] < N; ) { for(e = cur[x]; e; e = e->next) if(e->cap && h[e->to] + 1 == h[x]) break; if(e) { p[e->to] = cur[x] = e; A = min(A, e->cap); x = e->to; if(x == T) { flow += A; for(; x != S; x = p[x]->rev->to) { p[x]->cap -= A; p[x]->rev->cap += A; } A = INF; } } else { if(!--cnt[h[x]]) break; h[x] = N; for(e = head[x]; e; e = e->next) if(e->cap && h[e->to] + 1 < h[x]) { h[x] = h[e->to] + 1; cur[x] = e; } ++cnt[h[x]]; if(x != S) x = p[x]->rev->to; } } return flow;}int main() { int n, m, k; scanf("%d%d%d", &n, &m, &k); S = 0; T = n + m + 1; N = T + 1; memset(sumr, 0, sizeof sumr); memset(sumc, 0, sizeof sumc); memset(ok, -1, sizeof ok); for(int i = 1; i <= n; i++) scanf("%d", R + i); for(int i = 1; i <= m; i++) scanf("%d", C + i); int tot = n * m - k; while(k--) { int x, y; scanf("%d%d", &x, &y); ok[x][y] = false; sumr[x]++; sumc[y]++; } bool F = true; for(int i = 1; i <= n; i++) if(m - sumr[i] < R[i]) F = false; for(int i = 1; i <= m; i++) if(n - sumc[i] < C[i]) F = false; if(F) { for(int i = 1; i <= n; i++) addedge(S, i, m - sumr[i] - R[i]); for(int i = 1; i <= m; i++) addedge(i + n, T, n - sumc[i] - C[i]); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) if(ok[i][j]) addedge(i, j + n, INF); printf("%d\n", tot - maxFlow()); } else puts("JIONG!"); return 0;}----------------------------------------------------------------------
1458: 士兵占领
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 666 Solved: 386
[Submit][Status][Discuss]
Description
有一个M * N的棋盘,有的格子是障碍。现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵。我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵, 第j列至少放置了Cj个士兵。现在你的任务是要求使用最少个数的士兵来占领整个棋盘。Input
第一行两个数M, N, K分别表示棋盘的行数,列数以及障碍的个数。 第二行有M个数表示Li。 第三行有N个数表示Ci。 接下来有K行,每行两个数X, Y表示(X, Y)这个格子是障碍。Output
输出一个数表示最少需要使用的士兵个数。如果无论放置多少个士兵都没有办法占领整个棋盘,输出”JIONG!” (不含引号)Sample Input
4 4 41 1 1 1
0 1 0 3
1 4
2 2
3 3
4 3
Sample Output
4数据范围
M, N <= 100, 0 <= K <= M * N
HINT
Source
相关文章推荐
- HttpModule
- fork两次如何避免僵尸进程http://blog.chinaunix.net/uid-20729605-id-1884370.html
- 关于system()实现中阻塞sigchld信号的问题(转帖) http://blog.chinaunix.net/uid-17044717-id-2835670.html
- 对于linux下system()函数的深度理解(整理) (2013-02-07 08:58:54)http://blog.sina.com.cn/s/blog_8043547601017qk0.htm
- Afianl加载网络图片(延续)
- 十六、从网络中获取网页数据
- android-http协议部分认识
- iOS 开发之网络请求
- Photon服务器引擎(二)socket/TCP/UDP基础及Unity聊天室的实现
- 《深入理解Linux网络技术内幕》阅读笔记(八)
- [网络和多线程]8、GCD的其他用法
- iOS 网络请求(一些概念性方面的知识)
- TCP/IP协议原理与应用笔记12:单播、多播和广播地址(目的地址)
- (八) HTTP/2的各种帧定义
- C++基于TCP和UDP的socket通信
- 传输层:TCP 协议,转载自实验楼
- TCP/IP学习笔记
- 使用netstat检测及监测网络连接
- ECharts+BaiduMap+HT for Web网络拓扑图应用
- 安卓 AsyncHttpClient - “Content-Type not allowed!”