题目链接

题意

给定一个混合图,里面既有有向边也有无向边。问该图中是否存在一条路径,经过每条边恰好一次。

思路

从欧拉回路说起

首先回顾有向图欧拉回路的充要条件:\(\forall v\in G, d_{in}(v)=d_{out}(v)\).

现在这个图中有一些无向边,那怎么办?

那就转化成有向边呀。

对无向边随意定向,得到一个有向图。在这个有向图中,如果有\(\forall v\in G, abs(d_{in}(v)-d_{out}(v))\)为偶数,则将其中一些边反向,肯定能得到一个欧拉图。而若为奇数,则肯定不可以。

为什么?可以有两种考虑方式:

1.将所有的边看成无向边,那么,“对于每个点来说入度与出度之差绝对值为偶数”,这个条件就意味着,“对于每个点其度(=入度+出度)为偶数”,而这正是无向图欧拉回路的充要条件。现在我们得到了这个无向图中的欧拉回路,一路走一路定向,就得到了有向图中的欧拉回路。对比原有向图中的边的方向与现在得到的欧拉回路中的边的方向,将其中一些反向即可。
2. 直接从修改的角度想,将一条边反向的效果是,它的两个端点的入度与出度之差都变化2,最终可以使得达到每个点的入度与出度之差为0的效果,即得到欧拉回路。
(第二种说得不太严谨...)

问题转化

但是这道题是不是这么简单的呢?并不是。

为什么?因为我们并不能将其中任意一条边随意反向,不然这就跟给了一张无向图没什么差别了。

所以,限制就在于:将限定范围内的一些边反向,问能否得到一个欧拉图。

于是问题转化为,现有一些点,其中一些入度\(\gt\)出度,另一些出度\(\gt\)入度。将其中一些边反向,问能否满足所有的点的入度\(==\)出度

建图

由上面的关系可以很容易联想到网络流。

因为有向边是不可以反向的,所以对度数的改变没有任何贡献,不加入图中。

而经过定向成为有向边的边\(e=(u,v)\)在这一模型中的贡献是通过其反向可使\(u\)的入度-出度值增加\(2\),\(v\)的出度-入度值增加\(2\),故将之加入图中,权值为\(2\),意为将这一条边反向对度数的改变贡献为\(2\)。

接下来的步骤就很顺理成章了:

  1. 在 源点 到 出度\(\gt\)入度的点 之间加边,边权为出度与入度之差
  2. 在 入度\(\gt\)出度的点 到 汇点 之间加边,边权为入度与出度之差

最后只需判断最大流是否为满流即可。

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <iostream>
#define maxn 1010
#define maxm 10010
#define inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
struct Edge { int to, ne, c; }edge[maxm];
int dep[maxn], ne[maxn], n, m, tot, s,t, out[maxn], in[maxn];
void add(int u, int v, int c) {
edge[tot] = {v, ne[u], c};
ne[u] = tot++;
edge[tot] = {u, ne[v], 0};
ne[v] = tot++;
}
int bfs(int src) {
memset(dep, 0, sizeof dep);
dep[src] = 1;
queue<int> q;
while (!q.empty()) q.pop();
q.push(src);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = ne[u]; ~i; i = edge[i].ne) {
int v = edge[i].to;
if (edge[i].c > 0 && !dep[v]) dep[v] = dep[u] + 1, q.push(v);
}
}
return dep[t];
}
int dfs(int u, int flow) {
if (u == t) return flow;
int ret = 0;
for (int i = ne[u]; ~i; i = edge[i].ne) {
int v = edge[i].to;
if (edge[i].c > 0 && dep[v] == dep[u] + 1) {
int c = dfs(v, min(flow-ret, edge[i].c));
edge[i].c -= c;
edge[i^1].c += c;
ret += c;
if (ret == flow) break;
}
}
if (!flow) dep[u] = 0;
return ret;
}
void work() {
scanf("%d%d", &n, &m);
tot = 0; memset(ne, -1, sizeof ne);
memset(out, 0, sizeof out); memset(in, 0, sizeof in);
s = 0, t = n+1;
for (int i = 0; i < m; ++i) {
int u, v, t;
scanf("%d%d%d", &u, &v, &t);
if (!t) add(u, v, 2);
++out[u], ++in[v];
}
int cnt=0;
for (int i = 1; i <= n; ++i) {
if (abs(out[i]-in[i])&1) { puts("impossible"); return; }
if (out[i] > in[i]) add(s, i, out[i]-in[i]), cnt += out[i]-in[i];
else if (out[i] < in[i]) add(i, t, in[i]-out[i]);
}
int ret=0,ans=0;
while (bfs(s)) {
while (ret = dfs(s, inf)) ans += ret;
}
if (ans == cnt) puts("possible");
else puts("impossible");
}
int main() {
int T;
scanf("%d", &T);
while (T--) work();
return 0;
}

poj 1637 Sightseeing tour 混合图欧拉回路 最大流 建图的更多相关文章

  1. POJ 1637 Sightseeing tour ★混合图欧拉回路

    [题目大意]混合图欧拉回路(1 <= N <= 200, 1 <= M <= 1000) [建模方法] 把该图的无向边随便定向,计算每个点的入度和出度.如果有某个点出入度之差为 ...

  2. POJ 1637 Sightseeing tour (混合图欧拉回路)

    Sightseeing tour   Description The city executive board in Lund wants to construct a sightseeing tou ...

  3. POJ 1637 Sightseeing tour(混合图的欧拉回路)

    题目链接 建个图,套个模板. #include <cstdio> #include <cstring> #include <iostream> #include & ...

  4. POJ 1637 Sightseeing tour(最大流)

    POJ 1637 Sightseeing tour 题目链接 题意:给一些有向边一些无向边,问能否把无向边定向之后确定一个欧拉回路 思路:这题的模型很的巧妙,转一个http://blog.csdn.n ...

  5. POJ 1637 - Sightseeing tour - [最大流解决混合图欧拉回路]

    嗯,这是我上一篇文章说的那本宝典的第二题,我只想说,真TM是本宝典……做的我又痛苦又激动……(我感觉ACM的日常尽在这张表情中了) 题目链接:http://poj.org/problem?id=163 ...

  6. POJ 1637 Sightseeing tour(混合图欧拉回路+最大流)

    http://poj.org/problem?id=1637 题意:给出n个点和m条边,这些边有些是单向边,有些是双向边,判断是否能构成欧拉回路. 思路: 构成有向图欧拉回路的要求是入度=出度,无向图 ...

  7. POJ 1637 Sightseeing tour (混合图欧拉路判定)

    Sightseeing tour Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6986   Accepted: 2901 ...

  8. POJ 1637 Sightseeing tour (SAP | Dinic 混合欧拉图的判断)

    Sightseeing tour Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6448   Accepted: 2654 ...

  9. poj 1637 Sightseeing tour —— 最大流+欧拉回路

    题目:http://poj.org/problem?id=1637 建图很妙: 先给无向边随便定向,这样会有一些点的入度不等于出度: 如果入度和出度的差值不是偶数,也就是说这个点的总度数是奇数,那么一 ...

随机推荐

  1. C程序设计语言 -- 运算符优先级

    1. 运算符分类 算术运算符            [+, -,*, /, % , ++, --] 关系运算符             [>,  >=, <, <=] 相等性运 ...

  2. React学习记录二

    环境基本弄清楚了以后,开始总会写个hello world什么的,开发做了这么久了,就跳过这一步吧. 还是从打开vscode说起吧,这里文件菜单打开一个文件夹Demos,查看菜单打开集成终端,也可以使用 ...

  3. SpringBoot-Security-用户权限分配-项目搭建

    SpringBoot原则是约定优于配置,简化spring应用开发,去繁从简,产品级别的应用. SpringBoot有哪些优点1.快速创建独立运行的spring项目与主流框架集成 2.使用嵌入式的ser ...

  4. Codeforces Round #464 (Div. 2) B. Hamster Farm

    B. Hamster Farm time limit per test2 seconds memory limit per test256 megabytes Problem Description ...

  5. Python中*和**的区别

    Python中,(*)会把接收到的参数形成一个元组,而(**)则会把接收到的参数存入一个字典 我们可以看到,foo方法可以接收任意长度的参数,并把它们存入一个元组中 >>> def ...

  6. 【Remove Duplicates from Sorted Array】cpp

    题目: https://leetcode.com/problems/remove-duplicates-from-sorted-array/ Given a sorted array, remove ...

  7. ios开发学习笔记001-C语言基础知识

    先来学习一下C语言基础知识,总结如下: 在xcode下编写代码. 1.编写代码 2.编译:cc –c 文件名.c 编译成功会生成一个 .o的目标文件 3.链接:把目标文件.o和系统自带的库合并在一起, ...

  8. java包、类、方法、属性、常量命名规则

    必须用英文,不要用汉语拼音 1:包(package):用于将完成不同功能的类分门别类,放在不同的目录(包)下,包的命名规则:将公司域名反转作为包名.比如www.sohu.com 对于包名:每个字母都需 ...

  9. [HTTPS]pfx转jks

    keytool -importkeystore -srckeystore  src.pfx -srcstoretype pkcs12 -destkeystore trg.jks -deststoret ...

  10. SVD简化数据

    一,引言 我们知道,在实际生活中,采集到的数据大部分信息都是无用的噪声和冗余信息,那么,我们如何才能剔除掉这些噪声和无用的信息,只保留包含绝大部分重要信息的数据特征呢? 除了上次降到的PCA方法,本次 ...