[POJ 1637] Sightseeing tour(网络流)
题意
(混合图的欧拉回路判定)
给你一个既存在有向边, 又存在无向边的图. 问是否存在欧拉回路.
\(N ≤ 200, M ≤ 1000\)
题解
难点在于无向边. 考虑每个点的度数限制.
我们先对无向边任意定向, 现在每个点都有一个出度和入度的差; 而我们要求最终每个点出度和入度相等.
令它出度减去入度为 \(deg\) ,如果 \(deg\) 为奇数那么必不存在欧拉回路,因为每次我们修改一条边的定向,会使得入度 \(+1\) 出度 \(-1\) (或者相反)。那么变化后的 \(deg\) 总为奇数,就绝不可能成为 \(0\) 了。
然后接下来我们就需要判定之后改变边的定向能否满足要求。因为范围较小,我们继续可以联想到网络流。
首先我们建出超级源 \(S\) 、超级汇 \(T\) 。
- 把超级源向所有 \(deg > 0\) 的点 \(p\) 连上 \(S \to p\) 流量为 \(\displaystyle \frac{deg}{2}\) 的边。
- 把所有 \(deg < 0\) 的点 \(p\) 向超级汇连上 \(p \to T\) 流量为 \(- \displaystyle \frac{deg}{2}\) 的边。
- 把原图中存在的无向边我们连上 \(u \to v\) 流量为 \(1\) 的边。注意此处连 \(u \to v\) 的话,需要一开始假设最初的定向就是 \(u \to v\) 使得
++ deg[u], -- deg[v];
。
然后跑一遍网络流得到的流量如果和所有 \(deg > 0\) 的点的 \(deg\) 和相同,那么就是存在一组解的,否则就必不存在。
考虑为什么是这样的,因为我们每次流一条边,相当于把一条边 \(u \to v\) 反向成 \(v \to u\) ,使得给 \(u\) 的入度增加 \(1\) 出度减少 \(1\) ,所以 \(deg\) 会直接减少 \(2\) ,这就是为什么我们一开始流量为 \(\displaystyle |\frac{deg}{2}|\) 的原因。
如果满流的结果刚好是 \(\displaystyle\sum_{deg> 0} deg\) ,意味着所有点都修改正确了。
总结
对于有向图欧拉回路的题,牢记 入度 \(=\) 出度 才存在的性质。
代码
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstdlib>
#include<cstring>
#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
using namespace std;
inline bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
inline bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;}
inline int read() {
int x = 0, fh = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1;
for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
return x * fh;
}
void File() {
#ifdef zjp_shadow
freopen ("1637.in", "r", stdin);
freopen ("1637.out", "w", stdout);
#endif
}
int n, m;
const int N = 410, M = 5010, inf = 0x7f7f7f7f;
namespace Dinic {
int Head[N], Next[M], to[M], cap[M], e = 1;
inline void add_edge(int u, int v, int flow) { to[++ e] = v; Next[e] = Head[u]; Head[u] = e; cap[e] = flow; }
inline void Add(int u, int v, int flow) { add_edge(u, v, flow); add_edge(v, u, 0); }
int dis[N], S, T;
bool Bfs() {
queue<int> Q; Set(dis, 0); dis[S] = 1; Q.push(S);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
if (u == T) return true;
for (int i = Head[u]; i; i = Next[i]) if (cap[i]) {
int v = to[i];
if (!dis[v]) dis[v] = dis[u] + 1, Q.push(v);
}
}
return false;
}
int cur[N];
int Dfs(int u, int flow) {
if (u == T || !flow) return flow;
int res = 0, f;
for (int &i = cur[u]; i; i = Next[i]) if (cap[i]) {
int v = to[i]; if (dis[v] != dis[u] + 1) continue ;
if ((f = Dfs(v, min(flow, cap[i])))) {
cap[i] -= f; cap[i ^ 1] += f;
res += f; if (!(flow -= f)) break;
}
}
if (!res || !flow) dis[u] = 0;
return res;
}
int Run() {
int sum_flow = 0;
while (Bfs()) Cpy(cur, Head), sum_flow += Dfs(S, inf);
return sum_flow;
}
}
using namespace Dinic;
int deg[N];
inline bool IsOdd() { For (i, 1, n) if (deg[i] & 1) return true; return false; }
int main () {
File();
for (int cases = read(); cases; -- cases) {
n = read(); m = read(); e = 1;
For (i, 1, n + 2) Head[i] = deg[i] = 0;
For (i, 1, m) {
int u = read(), v = read(), type = read();
++ deg[u]; -- deg[v];
if (!type) Add(u, v, 1);
}
if (IsOdd()) { puts("impossible"); continue ; }
S = n + 1, T = S + 1; int tot = 0;
For (i, 1, n) {
if (deg[i] > 0) Add(S, i, deg[i] >> 1), tot += deg[i] >> 1;
if (deg[i] < 0) Add(i, T, (- deg[i]) >> 1);
}
puts(Run() == tot ? "possible" : "impossible");
}
return 0;
}
[POJ 1637] Sightseeing tour(网络流)的更多相关文章
- POJ 1637 Sightseeing tour(最大流)
POJ 1637 Sightseeing tour 题目链接 题意:给一些有向边一些无向边,问能否把无向边定向之后确定一个欧拉回路 思路:这题的模型很的巧妙,转一个http://blog.csdn.n ...
- 网络流(最大流) POJ 1637 Sightseeing tour
Sightseeing tour Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 8628 Accepted: 3636 ...
- POJ 1637 Sightseeing tour (混合图欧拉路判定)
Sightseeing tour Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 6986 Accepted: 2901 ...
- POJ 1637 - Sightseeing tour - [最大流解决混合图欧拉回路]
嗯,这是我上一篇文章说的那本宝典的第二题,我只想说,真TM是本宝典……做的我又痛苦又激动……(我感觉ACM的日常尽在这张表情中了) 题目链接:http://poj.org/problem?id=163 ...
- POJ 1637 Sightseeing tour (SAP | Dinic 混合欧拉图的判断)
Sightseeing tour Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 6448 Accepted: 2654 ...
- POJ 1637 Sightseeing tour
Sightseeing tour Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 9276 Accepted: 3924 ...
- POJ 1637 Sightseeing tour (混合图欧拉回路)
Sightseeing tour Description The city executive board in Lund wants to construct a sightseeing tou ...
- POJ 1637 Sightseeing tour 建图+网络流
题意: 给定一个混合图,所谓混合图就是图中既有单向边也有双向边,现在求这样的图是否存在欧拉回路. 分析: 存在欧拉回路的有向图,必须满足[入度==出度],现在,有些边已经被定向,所以我们直接记录度数即 ...
- POJ 1637 Sightseeing tour(混合图欧拉回路+最大流)
http://poj.org/problem?id=1637 题意:给出n个点和m条边,这些边有些是单向边,有些是双向边,判断是否能构成欧拉回路. 思路: 构成有向图欧拉回路的要求是入度=出度,无向图 ...
随机推荐
- 用python实现一个回文数
判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数. 示例 1: 输入: 121 输出: true 示例 2: 输入: -121 输出: false 解释: 从左向 ...
- 福州大学软件工程1816 | W班 第6次作业WordCount成绩排名
作业链接 WordCount进阶需求 评分细则 本次个人项目分数由两部分组成(博客分满分40分+程序得分满分60分) 博客评分细则(满分60,最终折算为40分) 在文章开头给出结对同学的博客链接.本作 ...
- Shell脚本2
5 Shell传递参数 我们可以在执行 Shell 脚本时,向脚本传递参数, 脚本内获取参数的格式为:$n.n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推…… ...
- mysql备份(导出)数据库,并恢复数据
导出某个数据库数据到文件中 假设要导出test这个数据库,那么可以在Linux命令行(不是在mysql中) [root@ubuntu /data]# mysqldump -uroot -p test ...
- Django 组件之 ----- content-type
Django 组件之 content-type的使用 一个表和多个表进行关联,但具体随着业务的加深,表不断的增加,关联的数量不断的增加,怎么通过一开始通过表的设计后,不在后期在修改表,彻底的解决这个问 ...
- Auzre系列1.1.1 —— 安装用于 IntelliJ 的 Azure 工具包
(文中大部分内容(95%)Azure官网上有,我只是把我自己实际操作中遇到的问题在这里阐述一下.) 先决条件 若要完成文章中的步骤,需要安装用于 IntelliJ 的 Azure 工具包,该工具包需要 ...
- apache benchmark 的简单安装与测试
1. 下载apache benchmark Copy From https://blog.csdn.net/fyqaccpt96/article/details/43272001 yum instal ...
- Oracle条件判断if...elsif
- WIndows下使用Grafana+InfluxDB打造监控系统
前言 对于一个运维DBA来说,了解数据库的TPS.QPS很有必要(QPS:每秒查询数,即对数据库每秒的DML的操作数:TPS:每秒事物处理,即对数据库每秒DDL操作数),通过了解他们,可以掌握一个实 ...
- 剑指offer(16)栈的压入、弹出序列
题目: 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈 ...