UVa 10735 (混合图的欧拉回路) Euler Circuit
题意:
给出一个图,有的边是有向边,有的是无向边。试找出一条欧拉回路。
分析:
按照往常的思维,遇到混合图,我们一般会把无向边拆成两条方向相反的有向边。
但是在这里却行不通了,因为拆成两条有向边的话,就表示这个边能“在两个相反方向各经过一次”。
而题意是这个边只能经过一次。
假设图中存在欧拉回路,则所有点的出度out(i) 等于 入度in(i)
不妨这样,先将所有的无向边任意定向,对于out(u) > in(u)的点,可以将已经定向的无向边u->v反向为v->u,这样out(u) - in(u)的值减2
如果把出度看做“货物”,则out(u) > in(u)的点提供货物,out(u) < in(u)的点需要货物,所以我们可以用网络流求最大流的算法,来使“供需平衡”
具体来说就是,给已经定向的无向边两点之间连一条容量为1的边,连接源点 与 所有“提供”出度的点,连接 所有“需要”出度的点 与 汇点。
如果求出来的最大流满载,也就是所有的出度都能被运到需要的地方,则有解。
在最大流中,如果流量为1则代表将该边反向的操作。
所以再建一个新图来求欧拉回路。
本题还有一个坑点就是可能存在平行边,所以求欧拉路径的过程中用 vis[u][v] = 1;的方法是行不通的了。
#include <bits/stdc++.h>
#define REP(i,n) for(int i = 0; i < (n); i++)
#define PB push_back
using namespace std; const int INF = ;
const int maxn = + ; struct Edge
{
int from, to, cap, flow;
Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {}
}; struct EdmondsKarp
{
int n, m;
vector<Edge> edges;
vector<int> G[maxn];
int a[maxn], p[maxn]; void Init(int n)
{
REP(i, n) G[i].clear();
edges.clear();
} void AddEdge(int from, int to, int cap)
{
edges.PB(Edge(from, to, cap, ));
edges.PB(Edge(to, from, , ));
m = edges.size();
G[from].PB(m-);
G[to].PB(m-);
} int MaxFlow(int s, int t)
{
int flow = ;
for(;;)
{
queue<int> Q;
Q.push(s);
memset(a, , sizeof(a));
a[s] = INF;
while(!Q.empty())
{
int x = Q.front(); Q.pop();
REP(i, G[x].size())
{
Edge& e = edges[G[x][i]];
if(!a[e.to] && e.cap > e.flow)
{
a[e.to] = min(a[x], e.cap - e.flow);
p[e.to] = G[x][i];
Q.push(e.to);
}
}
if(a[t]) break;
}
if(!a[t]) break;
for(int u = t; u != s; u = edges[p[u]].from)
{
edges[p[u]].flow += a[t];
edges[p[u]^].flow -= a[t];
}
flow += a[t];
}
return flow;
}
}g; int n, m;
int deg[maxn], u[maxn], v[maxn], id[maxn];
bool directed[maxn]; vector<int> G[maxn];//建新图,用来求欧拉回路
vector<int> vis[maxn];
vector<int> path;//欧拉回路 void Euler(int u)
{
REP(i, G[u].size()) if(!vis[u][i])
{
vis[u][i] = ;
Euler(G[u][i]);
path.PB(G[u][i]+);
}
} void print_answer()
{
REP(i, n) { G[i].clear(); vis[i].clear(); }
REP(i, m)
{
bool rev = false;
if(!directed[i] && g.edges[id[i]].flow > ) rev = true;//流量为1对应将该边反向
if(!rev) { G[u[i]].PB(v[i]); vis[u[i]].PB(); }
else { G[v[i]].PB(u[i]); vis[v[i]].PB(); }
} path.clear();
Euler();
printf("");
for(int i = path.size()-; i >= ; i--) printf(" %d", path[i]);
puts("");
} int main()
{
//freopen("in.txt", "r", stdin); int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &m);
g.Init(n+);
memset(deg, , sizeof(deg));
REP(i, m)
{
char d;
scanf("%d %d %c", &u[i], &v[i], &d);
u[i]--; v[i]--;
directed[i] = (d == 'D');
deg[u[i]]++; deg[v[i]]--;
if(!directed[i]) { id[i] = g.edges.size(); g.AddEdge(u[i], v[i], ); }//第i条边在网络流中的编号
} bool ok = true;
REP(i, m) if(deg[i] % != ) { ok = false; break; }//出入度之和不是偶数说明不存在欧拉回路 int s = n, t = n+;
if(ok)
{
int sum = ;
REP(i, n)
{
if(deg[i] > ) { sum += deg[i] / ; g.AddEdge(s, i, deg[i] / ); }
if(deg[i] < ) { g.AddEdge(i, t, -deg[i] / ); }
}
int flow = g.MaxFlow(s, t);
if(flow != sum) ok = false;//最大流不满载
} if(ok) print_answer(); else puts("No euler circuit exist");
if(T) puts("");
} return ;
}
代码君
UVa 10735 (混合图的欧拉回路) Euler Circuit的更多相关文章
- 紫书 例题 11-13 UVa 10735(混合图的欧拉回路)(最大流)
这道题写了两个多小时-- 首先讲一下怎么建模 我们的目的是让所有点的出度等于入度 那么我们可以把点分为两部分, 一部分出度大于入度, 一部分入度大于出度 那么显然, 按照书里的思路,将边方向后,就相当 ...
- bzoj2095: [Poi2010]Bridges(二分+混合图求欧拉回路)
传送门 这篇题解讲的真吼->这里 首先我们可以二分一个答案,然后把所有权值小于这个答案的都加入图中 那么问题就转化为一张混合图(既有有向边又有无向边)中是否存在欧拉回路 首先 无向图存在欧拉回路 ...
- [POJ1637]混合图的欧拉回路判定|网络流
混合图的欧拉回路判定 上一篇正好分别讲了有向图和无向图的欧拉回路判定方法 如果遇上了混合图要怎么做呢? 首先我们思考有向图的判定方法:所有点的出度=入度 我们可以先为无向边任意定一个向,算出此时所有顶 ...
- UVA 10735 Euler Circuit 混合图的欧拉回路(最大流,fluery算法)
题意:给一个图,图中有部分是向边,部分是无向边,要求判断是否存在欧拉回路,若存在,输出路径. 分析:欧拉回路的定义是,从某个点出发,每条边经过一次之后恰好回到出发点. 无向边同样只能走一次,只是不限制 ...
- ACM/ICPC 之 混合图的欧拉回路判定-网络流(POJ1637)
//网络流判定混合图欧拉回路 //通过网络流使得各点的出入度相同则possible,否则impossible //残留网络的权值为可改变方向的次数,即n个双向边则有n次 //Time:157Ms Me ...
- POJ 1637 混合图的欧拉回路判定
题意:一张混合图,判断是否存在欧拉回路. 分析参考: 混合图(既有有向边又有无向边的图)中欧拉环.欧拉路径的判定需要借助网络流! (1)欧拉环的判定:一开始当然是判断原图的基图是否连通,若不连通则一定 ...
- bzoj 2095: [Poi2010]Bridges(二分法+混合图的欧拉回路)
[题意] 给定n点m边的无向图,对于边u,v,从u到v边权为c,从v到u的边权为d,问能够经过每条边一次且仅一次,且最大权值最小的欧拉回路. [思路] 二分答案mid,然后切断权值大于mid的边,原图 ...
- POJ1637:Sightseeing tour(混合图的欧拉回路)
Sightseeing tour Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 10581 Accepted: 4466 ...
- POJ 1637 混合图求欧拉回路 最大流实现
前面讲过了无向图,有向图求欧拉回路,欧拉通路的做法.可以直接根据度数来判断,当然前提是这是一个连通图. 这道题既有无向边,又有有向边,然后求欧拉回路. 采用的方法是最大流. 具体处理方法. 首先,我们 ...
随机推荐
- 下拉刷新ListView实现原理
(1)主要是onScroll()方法和onTouchEvent()方法,先是onTouchEvent()的ACTION_DOWN,然后是 ACTION_MOVE和onScroll()方法同时进行,最后 ...
- javacript中的mvc设计模式
以下内容为原创翻译,翻译不对的地方还请原谅,凑合着看吧. 原文网址是: 来源:http://www.alexatnet.com/articles/model-view-controller-mvc-j ...
- ffmpeg 编码
编码可以简单理解为将连续的图片帧转变成视频流的过程.以H264为例给出编码的代码: int InitEncoderCodec(int width, int height) { auto enc = a ...
- 文本编辑器 markdown
http://www.cnblogs.com/youxia/p/linux014.html markdown对数学公式的支持http://www.linuxidc.com/Linux/2014-08/ ...
- SVN检出资源文件
一.选择new,输入svn,点击“从SVN检出项目” 二.选择“创建新的资源库位置”或“使用现有的资源库位置”(如果是新建,则需要地址和用户名.密码) 三.从现有的资源库选中项目
- CSS3属性box-shadow使用教程,css3box-shadow
CSS3的box-shadow属性可以让我们轻松实现图层阴影效果.我们来实战详解一下这个属性. 1. box-shadow属性的浏览器兼容性先来看一个这个属性的浏览器兼容性: Opera: 不知道是从 ...
- [CF]codeforces round#366(div2)滚粗记
开场心理活动:啊打完这场大概有1700了吧 中途心理活动:啊这个ABC看起来都随便做啊 死亡原因:欸怎么没网了 -75 .. A [题意]Hulk说完一句I hate会说that I love 然后是 ...
- Web App之一
JSP/HTML/CSS---------View(不包含任何的数据,只作为基本的layout) JS------------------------Data(update JSP/HTML)
- 初学tornado之MVC版helloworld
作者:the5fire | 标签: MVC tornado | 发布:2012-08-06 2:41 p.m. 文接上篇,看我一个简单的helloworld,虽然觉得这个框架着实精小,但是实际开发 ...
- ZOJ 3791 An Easy Game(DP)
题目链接 题意 : 给你两个长度为N的字符串,将第一个字符串每次只能变化M个,问变换K次之后变成第二个字符串一共有几种方法. 思路 : DP.dp[i][j]表示变了 i 次之后有j个不一样的字母的方 ...