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(带下界的最小流)***的更多相关文章

  1. [BZOJ2502]清理雪道解题报告|带下界的最小流

    滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机,每次飞 ...

  2. 【BZOJ-2502】清理雪道 有上下界的网络流(有下界的最小流)

    2502: 清理雪道 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 594  Solved: 318[Submit][Status][Discuss] ...

  3. BZOJ 3876: [Ahoi2014]支线剧情 带下界的费用流

    3876: [Ahoi2014]支线剧情 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=3876 Description [故事背景] 宅 ...

  4. POJ 3801/HDU 3157 Crazy Circuits | 有下界的最小流

    题目: POJ最近总是炸 所以还是用HDU吧http://acm.hdu.edu.cn/showproblem.php?pid=3157 题解: 题很长,但其实就是给个有源汇带下界网络流(+是源,-是 ...

  5. sgu 176 有源汇有上下界的最小流模板题

    /*参考博文:http://hi.baidu.com/dragon_eric123/item/82e259200ece744046996282 有上下界的有源最小流 */ #include<st ...

  6. POJ2396 Budget 【带下界的最大流】

    Budget Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 5962   Accepted: 2266   Special ...

  7. 【BZOJ-2893】征服王 最大费用最大流(带下界最小流)

    2893: 征服王 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 156  Solved: 48[Submit][Status][Discuss] D ...

  8. POJ 3801 有上下界最小流

    1: /** 2: POJ 3801 有上下界的最小流 3: 4: 1.对supersrc到supersink 求一次最大流,记为f1.(在有源汇的情况下,先使整个网络趋向必须边尽量满足的情况) 5: ...

  9. 【bzoj2502】清理雪道 有上下界最小流

    题目描述 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞 ...

随机推荐

  1. SQL_DML简单的操作

    ***********************************************声明*************************************************** ...

  2. C和指针 (pointers on C)——第十二章:利用结构和指针

    第十二章 利用结构和指针 这章就是链表.先单链表,后双向链表. 总结: 单链表是一种使用指针来存储值的数据结构.链表中的每一个节点包括一个字段,用于指向链表的下一个节点. 有一个独立的根指针指向链表的 ...

  3. IIS运行WCF服务报错

    试图加载格式不正确的程序   image 解决方法   image HTTP 错误 500.19   image 解决方法在控制面板————>程序————>启用或关闭windows功能—— ...

  4. WPF 动态模拟CPU 使用率曲线图

    原文:WPF 动态模拟CPU 使用率曲线图      在工作中经常会遇到需要将一组数据绘制成曲线图的情况,最简单的方法是将数据导入Excel,然后使用绘图功能手动生成曲线图.但是如果基础数据频繁更改, ...

  5. 【必须知道】Enum_Flags

    [Flags] enum AnyThings{ A=1, B=2, C=4, D=8 } 枚举赋值必须是2^n才可以,目的是实现他们的二进制表示中的 1 ,不要重叠,如 1=0001   2=0010 ...

  6. 如何使用C#创建Windows Webcam应用

    原文:如何使用C#创建Windows Webcam应用 最近想用C#写一个camera的应用.搜索了Google和StackOverflow,发现大部分的sample用了WIA或者DirectShow ...

  7. git + gerrit push 代码问题

    关于refs/for 和 refs/heads: 1.     这个不是git的规则,而是gerrit的规则, 2.     Branches, remote-tracking branches, a ...

  8. window下搭建qt开发环境编译、引用ace

    工作中经常用到ace.tao等,在windwo下的c++开发工具基本上就是vs20xx这些工具,还有些就是类似编辑工具例如:source insight等,前者比较大,打开.编译运行比较慢,二期针对a ...

  9. Java实现Qt的SIGNAL-SLOT机制(保存到Map中,从而将它们关联起来,收到信号进行解析,最后反射调用)

    SIGNAL-SLOT是Qt的一大特色,使用起来十分方便.在传统的AWT和Swing编程中,我们都是为要在 监听的对象上添加Listener监听器.被监听对象中保存有Listener的列表,当相关事件 ...

  10. Qt之QGraphicsEffect阴影、模糊效果

    Qt之QGraphicsEffect阴影.模糊效果 Qt之QGraphicsEffect阴影模糊效果 效果图 阴影和模糊效果 正常效果 代码 customshadoweffecth customsha ...