BZOJ 2502 清理雪道 有上下界的网络流
来源:互联网 发布:军人网络保密自查自纠 编辑:程序博客网 时间:2024/06/05 16:54
求DAG最少用多少条链覆盖完。
建立源汇连接入出度为0的点。
然后对于每条边,下界为1,上界为无穷大。
跑一次有上下界的最小流即可。
二分答案转化为判定性问题。
由于建立了超级源汇以后要建一条反向边,上界为总流量。
于是二分答案即可,判定转化以后的无源汇上下界网络流是否存在可行流即可。
代码写的有点复杂了。求建议?
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define FOR(i,j,k) for(i=j;i<=k;++i)const int N = 1005, M = 50005, inf = 0x7f7f7f7f;struct Graph { int h[N], p[M], v[M], w[M], q[M * 8], level[N], cnt, s, t; void init(int a, int b) { s = a; t = b; memset(h, -1, sizeof h); cnt = 0; } void add(int a, int b, int c) { p[cnt] = h[a]; v[cnt] = b; w[cnt] = c; h[a] = cnt++; p[cnt] = h[b]; v[cnt] = a; w[cnt] = 0; h[b] = cnt++; } bool bfs() { int f = 0, r = 0, u, i; memset(level, -1, sizeof level); q[r++] = s; level[s] = 0; while (f < r) { u = q[f++]; for (i = h[u]; i != -1; i = p[i]) if (w[i] > 0 && level[v[i]] == -1) { level[v[i]] = level[u] + 1; if (v[i] == t) return 1; q[r++] = v[i]; } } return level[t] != -1; } int dfs(int x, int low) { if (x == t) return low; int tmp, i, res = 0; for (i = h[x]; i != -1 && res < low; i = p[i]) if (w[i] > 0 && level[v[i]] == level[x] + 1) { tmp = dfs(v[i], min(low - res, w[i])); w[i] -= tmp; w[i ^ 1] += tmp; res += tmp; } if (!res) level[x] = -1; return res; } int dinic() { int ans = 0; while (bfs()) ans += dfs(s, inf); return ans; } void restore() { for (int i = 0; i < cnt; i += 2) w[i] += w[i ^ 1], w[i ^ 1] = 0; }};struct MinFlow : public Graph { bool valid() { for (int i = h[s]; i != -1; i = p[i]) if (w[i]) return 0; return 1; }} g;int main() { static int in[N]; int n, ss, st, s, t, p, i, j; scanf("%d", &n); ss = n + 2, st = n + 3, s = 0, t = n + 1; memset(in, 0, sizeof in); g.init(ss, st); FOR(i,1,n) { scanf("%d", &p); if (!p) g.add(i, t, inf); else while (p--) { scanf("%d", &j); g.add(i, st, 1); g.add(ss, j, 1); g.add(i, j, inf); in[j] = 1; } } FOR(i,1,n) if (!in[i]) g.add(s, i, inf); g.add(t, s, 0); int l = 1, r = 100000, ans = -1; while (l <= r) { int mid = l + r >> 1; g.restore(); g.w[g.cnt - 2] = mid; g.dinic(); if (g.valid()) r = mid - 1, ans = mid; else l = mid + 1; } printf("%d", ans); return 0;}
2502: 清理雪道
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 449 Solved: 231
[Submit][Status][Discuss]
Description
滑雪场坐落在FJ省西北部的若干座山上。
从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向。
你的团队负责每周定时清理雪道。你们拥有一架直升飞机,每次飞行可以从总部带一个人降落到滑雪场的某个地点,然后再飞回总部。从降落的地点出发,这个人可以顺着斜坡向下滑行,并清理他所经过的雪道。
由于每次飞行的耗费是固定的,为了最小化耗费,你想知道如何用最少的飞行次数才能完成清理雪道的任务。
Input
输入文件的第一行包含一个整数n (2 <= n <= 100) – 代表滑雪场的地点的数量。接下来的n行,描述1~n号地点出发的斜坡,第i行的第一个数为mi (0 <= mi < n) ,后面共有mi个整数,由空格隔开,每个整数aij互不相同,代表从地点i下降到地点aij的斜坡。每个地点至少有一个斜坡与之相连。
Output
输出文件的第一行是一个整数k – 直升飞机的最少飞行次数。
Sample Input
8
1 3
1 7
2 4 5
1 8
1 8
0
2 6 5
0
Sample Output
4
0 0
- BZOJ 2502 清理雪道 有上下界的网络流
- 【bzoj 2502】清理雪道(有上下界的网络流)
- [上下界网络流] BZOJ 2502 清理雪道
- BZOJ 2502(清理雪道-上下界网络流)
- [BZOJ 2502]清理雪道:上下界网络流
- 【bzoj2502】清理雪道 有上下界的网络流
- 2502: 清理雪道|有上下界的网络流之最小流
- 【BZOJ2502】清理雪道【有上下界的最小流】
- [BZOJ2502]清理雪道 有上下界的最小流
- bzoj 2406: 矩阵 (有上下界的网络流)
- [有上下界最小流] BZOJ2502: 清理雪道
- 有源汇上下界最小流 BZOJ 2502: 清理雪道
- [上下界有源汇最小流] BZOJ 2502: 清理雪道
- bzoj 2502(有上下界的最小流)
- BZOJ 2502 上下界网络流
- 有上下界的网络流
- 【有上下界的网络流】
- 有上下界限制的网络流
- linux 命令之 fork[1]
- iOS堆与栈的区别
- HBase分布式集群搭建
- C++创建二叉树
- //判断数组类型不包含indexOf方法
- BZOJ 2502 清理雪道 有上下界的网络流
- webx3对请求的处理流程详解一
- Java ConcurrentHashMap 源码分析(2)
- 课程Project总结 - 移动web大作业(不看微博)
- CQUPT登录页
- Linux 中mysql常用命令
- Matlab 中输入希腊字母
- 算法训练 安慰奶牛(最小生成树)
- Unity Shaders and Effects Cookbook (1-2)创建自定义漫反射光照模型