UVa 1440:Inspection(带下界的最小流)***
https://vjudge.net/problem/UVA-1440
题意:给出一个图,要求每条边都必须至少走一次,问最少需要一笔画多少次。
思路:看了好久才勉强看懂模板。良心推荐:学习地址。
看完这个大概就能懂了。
那条T->S的边的反向边的流量就是可行流的流量。
最小流就是去掉新的源点和新的汇点(保证必要弧)和T->S边后,从T往S跑最大流(尽量退流),最小流的答案就是原来T->S的反向边流量 - 第二次最大流的流量。
最大流就是去掉新的源点和新的汇点之后,再跑一遍最大流得到的就是答案。
最小流这里后面看别人的发现别人是先跑一遍(SS->ST)最大流,然后再连<T,S>边,再跑一遍(SS->ST)最大流。然而论文里面是先连<T,S>边,跑一遍(SS->ST)最大流,然后删掉<T,S>边和所有与SS、ST相连的边,跑一遍(T->S)的最大流。
看了N久还是不能完全理解。
记得多组数组!!!WA了一晚上。
写法一:
#include <bits/stdc++.h>
using namespace std;
#define N 210
#define INF 0x3f3f3f3f
struct Edge {
int u, v, nxt, cap;
} edge[N*N];
int head[N], tot, dis[N], cur[N], pre[N], gap[N], in[N], out[N], S, T, SS, ST; void Add(int u, int v, int cap) {
edge[tot].u = u, edge[tot].v = v, edge[tot].nxt = head[u], edge[tot].cap = cap, head[u] = tot++;
edge[tot].u = v, edge[tot].v = u, edge[tot].nxt = head[v], edge[tot].cap = , head[v] = tot++;
} int BFS(int T) {
memset(dis, INF, sizeof(dis));
memset(gap, , sizeof(gap));
memcpy(cur, head, sizeof(cur));
dis[T] = , gap[]++;
queue<int> que; que.push(T);
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(dis[v] == INF) {
dis[v] = dis[u] + ;
gap[dis[v]]++;
que.push(v);
}
}
}
} int ISAP(int S, int T, int n) {
BFS(T);
int u = pre[S] = S, i, index, flow, ans = ;
while(dis[S] < n) {
if(u == T) {
flow = INF;
for(i = S; i != T; i = edge[cur[i]].v)
if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i;
for(i = S; i != T; i = edge[cur[i]].v)
edge[cur[i]].cap -= flow, edge[cur[i]^].cap += flow;
ans += flow, u = index;
}
for(i = cur[u]; ~i; i = edge[i].nxt) if(edge[i].cap && dis[edge[i].v] + == dis[u]) break;
if(~i) {
cur[u] = i; pre[edge[i].v] = u; u = edge[i].v;
} else {
if(--gap[dis[u]] == ) break;
int md = n;
for(int i = head[u]; ~i; i = edge[i].nxt)
if(edge[i].cap && dis[edge[i].v] < md) md = dis[edge[i].v], cur[u] = i;
gap[dis[u] = md + ]++;
u = pre[u];
}
}
return ans;
} void Delete() {
for(int i = head[SS]; ~i; i = edge[i].nxt) edge[i].cap = edge[i^].cap = ;
for(int i = head[ST]; ~i; i = edge[i].nxt) edge[i].cap = edge[i^].cap = ;
edge[tot-].cap = edge[(tot-)^].cap = ;
} void Update(int n) {
for(int u = ; u <= n; u++) {
for(int i = head[u]; ~i; i = edge[i].nxt) {
if(edge[i].v == S || edge[i].v == T || (i & )) continue;
edge[i^].cap++;
}
}
} void Dfs(int u) {
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(i & || !edge[i^].cap || v == S || v == T || v == SS || v == ST) continue;
edge[i^].cap--;
printf(" %d", v);
Dfs(v);
break;
}
} int main() {
int n;
while(~scanf("%d", &n)) {
memset(head, -, sizeof(head)); tot = ;
memset(out, , sizeof(out)); memset(in, , sizeof(in));
S = n + , T = n + , SS = n + , ST = n + ;
for(int i = ; i <= n; i++) {
int k; scanf("%d", &k);
while(k--) {
int x; scanf("%d", &x);
out[i]++; in[x]++;
Add(i, x, INF);
}
}
for(int i = ; i <= n; i++) {
if(!out[i]) Add(i, T, INF);
if(!in[i]) Add(S, i, INF);
int deg = in[i] - out[i];
if(deg > ) Add(SS, i, deg);
else if(deg < ) Add(i, ST, -deg);
}
Add(T, S, INF);
ISAP(SS, ST, ST + );
int ans = edge[tot-].cap;
Delete();
ans -= ISAP(T, S, T + );
printf("%d\n", ans);
Update(n);
int cur = head[S];
for(int k = ; k <= ans; k++) {
for(int i = cur; ~i; i = edge[i].nxt) {
if(!(i & ) && edge[i^].cap) {
int v = edge[i].v;
edge[i^].cap--;
printf("%d", v);
Dfs(edge[i].v);
puts("");
cur = i;
break;
}
}
}
}
return ;
}
写法二:
#include <bits/stdc++.h>
using namespace std;
#define N 210
#define INF 0x3f3f3f3f
struct Edge {
int u, v, nxt, cap;
} edge[N*N];
int head[N], tot, dis[N], cur[N], pre[N], gap[N], in[N], out[N], S, T, SS, ST, n; void Add(int u, int v, int cap) {
edge[tot].u = u, edge[tot].v = v, edge[tot].nxt = head[u], edge[tot].cap = cap, head[u] = tot++;
edge[tot].u = v, edge[tot].v = u, edge[tot].nxt = head[v], edge[tot].cap = , head[v] = tot++;
} int BFS(int T) {
memset(dis, INF, sizeof(dis));
memset(gap, , sizeof(gap));
memcpy(cur, head, sizeof(cur));
dis[T] = , gap[]++;
queue<int> que; que.push(T);
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(dis[v] == INF) {
dis[v] = dis[u] + ;
gap[dis[v]]++;
que.push(v);
}
}
}
} int ISAP(int S, int T, int n) {
BFS(T);
int u = pre[S] = S, i, index, flow, ans = ;
while(dis[S] < n) {
if(u == T) {
flow = INF;
for(i = S; i != T; i = edge[cur[i]].v)
if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i;
for(i = S; i != T; i = edge[cur[i]].v)
edge[cur[i]].cap -= flow, edge[cur[i]^].cap += flow;
ans += flow, u = index;
}
for(i = cur[u]; ~i; i = edge[i].nxt) if(edge[i].cap && dis[edge[i].v] + == dis[u]) break;
if(~i) {
cur[u] = i; pre[edge[i].v] = u; u = edge[i].v;
} else {
if(--gap[dis[u]] == ) break;
int md = n;
for(int i = head[u]; ~i; i = edge[i].nxt)
if(edge[i].cap && dis[edge[i].v] < md) md = dis[edge[i].v], cur[u] = i;
gap[dis[u] = md + ]++;
u = pre[u];
}
}
return ans;
} void Delete() {
for(int i = head[SS]; ~i; i = edge[i].nxt) edge[i].cap = edge[i^].cap = ;
for(int i = head[ST]; ~i; i = edge[i].nxt) edge[i].cap = edge[i^].cap = ;
edge[tot-].cap = edge[(tot-)^].cap = ;
} void Update(int n) {
for(int u = ; u <= n; u++) {
for(int i = head[u]; ~i; i = edge[i].nxt) {
if(edge[i].v == S || edge[i].v == T || (i & )) continue;
edge[i^].cap++;
}
}
} void Dfs(int u) {
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(i & || !edge[i^].cap || v > n) continue;
edge[i^].cap--;
printf(" %d", v);
Dfs(v); break;
}
} void Solve() {
for(int u = ; u <= n; u++) {
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(i & ) continue;
edge[i^].cap++;
}
}
for(int i = head[S]; ~i; i = edge[i].nxt) {
if(i & ) continue;
while(edge[i^].cap) {
edge[i^].cap--;
int v = edge[i].v;
printf("%d", v);
Dfs(v); puts("");
}
}
} int main() {
while(~scanf("%d", &n)) {
memset(head, -, sizeof(head)); tot = ;
memset(out, , sizeof(out)); memset(in, , sizeof(in));
S = n + , T = n + , SS = n + , ST = n + ;
for(int i = ; i <= n; i++) {
int k; scanf("%d", &k);
while(k--) {
int x; scanf("%d", &x);
out[i]++; in[x]++;
Add(i, x, INF);
}
}
for(int i = ; i <= n; i++) {
if(!out[i]) Add(i, T, INF);
if(!in[i]) Add(S, i, INF);
int deg = in[i] - out[i];
if(deg > ) Add(SS, i, deg);
else if(deg < ) Add(i, ST, -deg);
}
ISAP(SS, ST, ST + );
Add(T, S, INF);
int ans = ISAP(SS, ST, ST + );
printf("%d\n", ans);
Solve();
}
return ;
}
UVa 1440:Inspection(带下界的最小流)***的更多相关文章
- [BZOJ2502]清理雪道解题报告|带下界的最小流
滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机,每次飞 ...
- 【BZOJ-2502】清理雪道 有上下界的网络流(有下界的最小流)
2502: 清理雪道 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 594 Solved: 318[Submit][Status][Discuss] ...
- BZOJ 3876: [Ahoi2014]支线剧情 带下界的费用流
3876: [Ahoi2014]支线剧情 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=3876 Description [故事背景] 宅 ...
- POJ 3801/HDU 3157 Crazy Circuits | 有下界的最小流
题目: POJ最近总是炸 所以还是用HDU吧http://acm.hdu.edu.cn/showproblem.php?pid=3157 题解: 题很长,但其实就是给个有源汇带下界网络流(+是源,-是 ...
- sgu 176 有源汇有上下界的最小流模板题
/*参考博文:http://hi.baidu.com/dragon_eric123/item/82e259200ece744046996282 有上下界的有源最小流 */ #include<st ...
- POJ2396 Budget 【带下界的最大流】
Budget Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 5962 Accepted: 2266 Special ...
- 【BZOJ-2893】征服王 最大费用最大流(带下界最小流)
2893: 征服王 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 156 Solved: 48[Submit][Status][Discuss] D ...
- POJ 3801 有上下界最小流
1: /** 2: POJ 3801 有上下界的最小流 3: 4: 1.对supersrc到supersink 求一次最大流,记为f1.(在有源汇的情况下,先使整个网络趋向必须边尽量满足的情况) 5: ...
- 【bzoj2502】清理雪道 有上下界最小流
题目描述 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞 ...
随机推荐
- Angular route传参
从 router-link-page1 跳转 router-link-page2 和 router-link-page3 通过自定义路由 设置router-link-page2的路由后有3个参数,pa ...
- WPF Datagrid with some read-only rows - Stack Overflow
原文:WPF Datagrid with some read-only rows - Stack Overflow up vote 21 down vote accepted I had the sa ...
- CentOS 6安装桌面
安装图形界面 yum -y groupinstall "X Window System" "Chinese Support" "Desktop&quo ...
- DataGridView动态添加新行的两种方法
简单介绍如何为DataGridView控件动态添加新行的两种方 法: 方法一: int index=this.dataGridView1.Rows.Add();this.dataGridView1.R ...
- AY的Dapper研究学习-继续深入-C#开发-aaronyang技术分享
原文:AY的Dapper研究学习-继续深入-C#开发-aaronyang技术分享 ====================www.ayjs.net 杨洋 wpfui.com ...
- WPF属性(一)依赖属性
原文:WPF属性(一)依赖属性 依赖属性是一种可以自己没有值,并能通过使用Binding从数据源获得值的属性,拥有依赖属性的对象称为依赖对象,在传统开发中,一个对象所占用的内存在调用new操作符进行实 ...
- centos7安装 lamp
1.安装apache yum install httpd #根据提示,输入Y安装即可成功安装 systemctl start httpd.service #启动apache systemctl sto ...
- 图像滤镜艺术---(Instagram)1977滤镜
原文:图像滤镜艺术---(Instagram)1977滤镜 图像特效---(Instagram)1977滤镜 本文介绍1977这个滤镜的具体实现,这个滤镜最早是Instagram中使用的 ,由于Ins ...
- Unpaired/Partially/Unsupervised Image Captioning
这篇涉及到以下三篇论文: Unpaired Image Captioning by Language Pivoting (ECCV 2018) Show, Tell and Discriminate: ...
- C# ACCESS 查询提示“至少一个参数没有被指定”问题
错误的SQL指令如下: sqlStr = “select * from tb_userInfo where userName=” + userName; //错误的 sql 指令 正确的SQL ...