题目链接

题意

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

思路

从欧拉回路说起

首先回顾有向图欧拉回路的充要条件:\(\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. window.onload和$(docunment).ready的区别

    浏览器加载完DOM后,会通过javascript为DOM元素添加事件,在javascript中,通常使用window.onload()方法. 在jquery中,则使用$(document).ready ...

  2. 科学计算库Numpy——数值计算

    矩阵 求和 乘积 最大值和最小值 最大值和最小值的位置 平均数 标准差 方差 限制 四舍五入

  3. Neon Lights in Hong Kong【香港霓虹灯】

    Neon Lights in Hong Kong Neon is to Hong Kong as red phone booths are to London and fog is to San Fr ...

  4. A1095 Cars on Campus (30)(30 分)

    A1095 Cars on Campus (30)(30 分) Zhejiang University has 6 campuses and a lot of gates. From each gat ...

  5. 序列化模块--json模块--pickle模块-shelve模块

    什么叫序列化? 序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或通过网络传播到远程,因为硬盘或网络传输时只能接受bytes 例: 把内存数据 转成字符 # data ={# 'roles ...

  6. ios开发学习笔记004-进制与位运算

    进制 二进制   0 1组成,封2进1 八进制 0-7组成,封8进1 十进制 0-9组成,封10进1 十六进制 0-15组成,封16进1 printf以不同进制形式进行输出 变量的内存地址形式 变量在 ...

  7. 几种常见的Android自动化测试框架及其应用

    随着Android应用得越来越广,越来越多的公司推出了自己移动应用测试平台.例如,百度的MTC.东软易测云.Testin云测试平台…….由于自己所在项目组就是做终端测试工具的,故抽空了解了下几种常见的 ...

  8. jqgrid postData setGridParam 调用多次时查询条件累加的问题

    var postData = $(gridId).jqGrid("getGridParam", "postData"); $.each(paras, funct ...

  9. 学习成绩>=90分的同学用A表示,60-89分之间的用B表示,60分以下的用利用条件运算符的嵌套来完成此题:C表示。

    # -*- coding: utf8 -*- # Author:wxq #python 2.7 #题目:学习成绩>=90分的同学用A表示,60-89分之间的用B表示,60分以下的用利用条件运算符 ...

  10. 如何利用c++编写不能被继承、但可以在类外定义对象的类

    #include <iostream> #include<string> #include<map> #include<vector> #include ...