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. style文件的指定

    新建资源文件   写资源文件 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/prese ...

  2. WPF扩展标记X:STATIC

    原文:WPF扩展标记X:STATIC public class XStaic     {         public static string Content = "确定"; ...

  3. delphi判断线程状态函数(使用GetExitCodeThread API函数去判断线程的句柄)

    //判断线程是否释放//返回值:0-已释放:1-正在运行:2-已终止但未释放://3-未建立或不存在 function CheckThreadFreed(aThread: TThread): Byte ...

  4. wpf屏蔽快捷键alt+space,alt+F4

    /// <summary>        /// 阻止 alt+f4和alt+space 按键        /// </summary>        /// <par ...

  5. 零元学Expression Blend 4 - Chapter 28 ListBox的基本运用与更改预设样式

    原文:零元学Expression Blend 4 - Chapter 28 ListBox的基本运用与更改预设样式 本章将先教大家认识ListBox的基本运用与更改预设样式 本章将先教大家认识List ...

  6. 零元学Expression Blend 4 - Chapter 3 熟悉操作第一步(制作一个猴子脸)

    原文:零元学Expression Blend 4 - Chapter 3 熟悉操作第一步(制作一个猴子脸) 本篇内容会教你如何使用笔刷.钢笔.渐层以及透明度的调整,还有如何转化图层和路径,最重要的是要 ...

  7. mysql 服务压缩包安装,用户创建

    wind7上安装mysql记录: 1.下载的包中没有ini配置文件,需要根目录手动创建my.ini文件 内容如下: [client]port=3306default-character-set=utf ...

  8. Add-AppxProvisionedPackage

    原文: Add-AppxProvisionedPackage Adds an app package (.appx) that will install for each new user to a ...

  9. Mac App Store应用签名和pkg签名,查看签名

    App签名 只有用苹果颁发的证书签名的应用才能在App Store上进行销售,所以我们开发的应用必须打上签名. 签名有两种方式,一是使用Xcode,在配置里面设置签名,编译出来的app就有了签名:二是 ...

  10. C# 遍历窗体控件顺序问题

    今天在做C# winform 窗体控件遍历时遇到控件顺序的问题,也就是控件被遍历的先后问题.实际情况如下所述. 窗体界面如下: 界面构成是:主界面有一个 Panel (Panel_14),Panel_ ...