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. 记一次删除Git记录中的大文件的过程

    app/test/target/ #查看大文件 git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/ ...

  2. nyoj 92 图片实用面积【bfs】

    图像实用区域 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描写叙述 "ACKing"同学曾经做一个图像处理的项目时.遇到了一个问题,他须要摘取出图片中某 ...

  3. WPF 附加属性的使用

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...

  4. 通通玩blend美工(7)——简约而不简单的块

    原文:通通玩blend美工(7)--简约而不简单的块 最近在研发一个WPF快速开发框架,满脑子都是各种逻辑各种模式,写一篇比较休闲娱乐的博客,宣泄下我对美工的热爱. 我一直以来有意无意在手机应用或者各 ...

  5. iOS UITableView动态隐藏或显示Item

    通过改变要隐藏的item的高度实现隐藏和显示item 1.创建UITableView #import "ViewController.h" @interface ViewContr ...

  6. Win8 Metro(C#)数字图像处理--3.4图像信息熵计算

    原文:Win8 Metro(C#)数字图像处理--3.4图像信息熵计算 [函数代码] /// <summary> /// Entropy of one image. /// </su ...

  7. iOS中的加密操作

    最近项目中用到了一些加密操作,在这里简单总结了一下.总的来说加密分为对称加密和非对称加密两种,下面对这两种加密方式作一个简单的说明. 对称加密(Symmetric Cryptography) 对称加密 ...

  8. 编译时MSIL注入--实践Mono Cecil(1)

    原文:编译时MSIL注入--实践Mono Cecil(1) 紧接上两篇浅谈.NET编译时注入(C#-->IL)和浅谈VS编译自定义编译任务—MSBuild Task(csproject),在第一 ...

  9. WebApi 中FromUri参数自动解析成实体的要求

    条件一:类属性名称必须和参数名称相同(不分大小写) 条件二:API参数必须以[FromUri]来修饰(数组也需要添加,否则参数传递不了) 条件三:属性类型为“类”的,如果使用类名(导航属性在本类的名称 ...

  10. centos 7 安装 git 2.22.0

    1.安装所需软件包 yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel yum install gcc ...