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省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞 ...
随机推荐
- 【转】postgresql 9.4 在linux环境的安装步骤详解
本文章来为各位介绍一篇关于postgresql 9.4 在linux环境的安装步骤详解,希望文章能够对各位新手朋友带来帮助的哦. 环境说明系统:centos 6.4 64位软件:postgresql ...
- ntp时间同步,各种配置方法
1 Windows xp NTP服务器的配置(2003配置方式一样) 1) 首先需要关闭作为NTP服务器的windows系统自带的防火墙,否则将同步不成功. 2) 单击“开始”,单击“运行”,键入 r ...
- js 层的显示和隐藏
<!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- SQL介绍及MySql的安装
数据库及SQL概念 数据库是按照数据结构存储和组织数据的仓库 结构化查询语言(Structured Query Language)简称SQL MySql:DBMS MySql安装 安装MySql服务端 ...
- DateTimeToGreenUnix
@暗夜魔尊 { Unix date conversion support with time-zone detect } function DateTimeToGreenUnix(const AVal ...
- WIFI Manager
Vistumbler - wifi managerhttps://www.vistumbler.net/downloads.htmlhttps://github.com/RIEI
- Markdown 语法简体中文版
Markdown 语法简体中文版(fork 于繁体中文版 http://markdown.tw/ ) http://wowubuntu.com/markdownhttps://github.com/r ...
- 一条命令,秒秒钟完成MD5、SHA1校验,这就叫效率!
相信很多奋斗在运维战线的小伙伴们经常会遇到版本升级之类的问题.笔者之前所在的公司每次进行版本发布的时候都会附带MD5校验哈希值,每次升级之前一般都要核对MD5哈希值的,刚刚开始的时候对Linux并不是 ...
- 关于Android开发四大组件
文章主要是讲Android开发的四大组件,本文主要分为 文章源自:http://www.cnblogs.com/pepcod/archive/2013/02/11/2937403.html 一.Act ...
- .NET错误:The tag 'BusyIndicator' ('CallMethodAction')does not exist in XML namespace
将一个项目由VS2010升级为VS2012后,在确保代码无误的情况下编译程序出现以下错误提示: 解决方法:将4.0.0.0的程序集Microsoft.Expression.Interactions.及 ...