题意:

给出一个图,有的边是有向边,有的是无向边。试找出一条欧拉回路。

分析:

按照往常的思维,遇到混合图,我们一般会把无向边拆成两条方向相反的有向边。

但是在这里却行不通了,因为拆成两条有向边的话,就表示这个边能“在两个相反方向各经过一次”。

而题意是这个边只能经过一次。

假设图中存在欧拉回路,则所有点的出度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;的方法是行不通的了。

  1. #include <bits/stdc++.h>
  2. #define REP(i,n) for(int i = 0; i < (n); i++)
  3. #define PB push_back
  4. using namespace std;
  5.  
  6. const int INF = ;
  7. const int maxn = + ;
  8.  
  9. struct Edge
  10. {
  11. int from, to, cap, flow;
  12. Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {}
  13. };
  14.  
  15. struct EdmondsKarp
  16. {
  17. int n, m;
  18. vector<Edge> edges;
  19. vector<int> G[maxn];
  20. int a[maxn], p[maxn];
  21.  
  22. void Init(int n)
  23. {
  24. REP(i, n) G[i].clear();
  25. edges.clear();
  26. }
  27.  
  28. void AddEdge(int from, int to, int cap)
  29. {
  30. edges.PB(Edge(from, to, cap, ));
  31. edges.PB(Edge(to, from, , ));
  32. m = edges.size();
  33. G[from].PB(m-);
  34. G[to].PB(m-);
  35. }
  36.  
  37. int MaxFlow(int s, int t)
  38. {
  39. int flow = ;
  40. for(;;)
  41. {
  42. queue<int> Q;
  43. Q.push(s);
  44. memset(a, , sizeof(a));
  45. a[s] = INF;
  46. while(!Q.empty())
  47. {
  48. int x = Q.front(); Q.pop();
  49. REP(i, G[x].size())
  50. {
  51. Edge& e = edges[G[x][i]];
  52. if(!a[e.to] && e.cap > e.flow)
  53. {
  54. a[e.to] = min(a[x], e.cap - e.flow);
  55. p[e.to] = G[x][i];
  56. Q.push(e.to);
  57. }
  58. }
  59. if(a[t]) break;
  60. }
  61. if(!a[t]) break;
  62. for(int u = t; u != s; u = edges[p[u]].from)
  63. {
  64. edges[p[u]].flow += a[t];
  65. edges[p[u]^].flow -= a[t];
  66. }
  67. flow += a[t];
  68. }
  69. return flow;
  70. }
  71. }g;
  72.  
  73. int n, m;
  74. int deg[maxn], u[maxn], v[maxn], id[maxn];
  75. bool directed[maxn];
  76.  
  77. vector<int> G[maxn];//建新图,用来求欧拉回路
  78. vector<int> vis[maxn];
  79. vector<int> path;//欧拉回路
  80.  
  81. void Euler(int u)
  82. {
  83. REP(i, G[u].size()) if(!vis[u][i])
  84. {
  85. vis[u][i] = ;
  86. Euler(G[u][i]);
  87. path.PB(G[u][i]+);
  88. }
  89. }
  90.  
  91. void print_answer()
  92. {
  93. REP(i, n) { G[i].clear(); vis[i].clear(); }
  94. REP(i, m)
  95. {
  96. bool rev = false;
  97. if(!directed[i] && g.edges[id[i]].flow > ) rev = true;//流量为1对应将该边反向
  98. if(!rev) { G[u[i]].PB(v[i]); vis[u[i]].PB(); }
  99. else { G[v[i]].PB(u[i]); vis[v[i]].PB(); }
  100. }
  101.  
  102. path.clear();
  103. Euler();
  104. printf("");
  105. for(int i = path.size()-; i >= ; i--) printf(" %d", path[i]);
  106. puts("");
  107. }
  108.  
  109. int main()
  110. {
  111. //freopen("in.txt", "r", stdin);
  112.  
  113. int T;
  114. scanf("%d", &T);
  115. while(T--)
  116. {
  117. scanf("%d%d", &n, &m);
  118. g.Init(n+);
  119. memset(deg, , sizeof(deg));
  120. REP(i, m)
  121. {
  122. char d;
  123. scanf("%d %d %c", &u[i], &v[i], &d);
  124. u[i]--; v[i]--;
  125. directed[i] = (d == 'D');
  126. deg[u[i]]++; deg[v[i]]--;
  127. if(!directed[i]) { id[i] = g.edges.size(); g.AddEdge(u[i], v[i], ); }//第i条边在网络流中的编号
  128. }
  129.  
  130. bool ok = true;
  131. REP(i, m) if(deg[i] % != ) { ok = false; break; }//出入度之和不是偶数说明不存在欧拉回路
  132.  
  133. int s = n, t = n+;
  134. if(ok)
  135. {
  136. int sum = ;
  137. REP(i, n)
  138. {
  139. if(deg[i] > ) { sum += deg[i] / ; g.AddEdge(s, i, deg[i] / ); }
  140. if(deg[i] < ) { g.AddEdge(i, t, -deg[i] / ); }
  141. }
  142. int flow = g.MaxFlow(s, t);
  143. if(flow != sum) ok = false;//最大流不满载
  144. }
  145.  
  146. if(ok) print_answer(); else puts("No euler circuit exist");
  147. if(T) puts("");
  148. }
  149.  
  150. return ;
  151. }

代码君

UVa 10735 (混合图的欧拉回路) Euler Circuit的更多相关文章

  1. 紫书 例题 11-13 UVa 10735(混合图的欧拉回路)(最大流)

    这道题写了两个多小时-- 首先讲一下怎么建模 我们的目的是让所有点的出度等于入度 那么我们可以把点分为两部分, 一部分出度大于入度, 一部分入度大于出度 那么显然, 按照书里的思路,将边方向后,就相当 ...

  2. bzoj2095: [Poi2010]Bridges(二分+混合图求欧拉回路)

    传送门 这篇题解讲的真吼->这里 首先我们可以二分一个答案,然后把所有权值小于这个答案的都加入图中 那么问题就转化为一张混合图(既有有向边又有无向边)中是否存在欧拉回路 首先 无向图存在欧拉回路 ...

  3. [POJ1637]混合图的欧拉回路判定|网络流

    混合图的欧拉回路判定 上一篇正好分别讲了有向图和无向图的欧拉回路判定方法 如果遇上了混合图要怎么做呢? 首先我们思考有向图的判定方法:所有点的出度=入度 我们可以先为无向边任意定一个向,算出此时所有顶 ...

  4. UVA 10735 Euler Circuit 混合图的欧拉回路(最大流,fluery算法)

    题意:给一个图,图中有部分是向边,部分是无向边,要求判断是否存在欧拉回路,若存在,输出路径. 分析:欧拉回路的定义是,从某个点出发,每条边经过一次之后恰好回到出发点. 无向边同样只能走一次,只是不限制 ...

  5. ACM/ICPC 之 混合图的欧拉回路判定-网络流(POJ1637)

    //网络流判定混合图欧拉回路 //通过网络流使得各点的出入度相同则possible,否则impossible //残留网络的权值为可改变方向的次数,即n个双向边则有n次 //Time:157Ms Me ...

  6. POJ 1637 混合图的欧拉回路判定

    题意:一张混合图,判断是否存在欧拉回路. 分析参考: 混合图(既有有向边又有无向边的图)中欧拉环.欧拉路径的判定需要借助网络流! (1)欧拉环的判定:一开始当然是判断原图的基图是否连通,若不连通则一定 ...

  7. bzoj 2095: [Poi2010]Bridges(二分法+混合图的欧拉回路)

    [题意] 给定n点m边的无向图,对于边u,v,从u到v边权为c,从v到u的边权为d,问能够经过每条边一次且仅一次,且最大权值最小的欧拉回路. [思路] 二分答案mid,然后切断权值大于mid的边,原图 ...

  8. POJ1637:Sightseeing tour(混合图的欧拉回路)

    Sightseeing tour Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 10581   Accepted: 4466 ...

  9. POJ 1637 混合图求欧拉回路 最大流实现

    前面讲过了无向图,有向图求欧拉回路,欧拉通路的做法.可以直接根据度数来判断,当然前提是这是一个连通图. 这道题既有无向边,又有有向边,然后求欧拉回路. 采用的方法是最大流. 具体处理方法. 首先,我们 ...

随机推荐

  1. 移动端页面使用rem来做适配

    文/九彩拼盘(简书作者)原文链接:http://www.jianshu.com/p/eb05c775d3c6著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. rem介绍 rem(font ...

  2. 【BZOJ】【2733】【HNOI2012】永无乡

    平衡树+启发式合并+并查集 因为要求一坨数中第k大的……用平衡树会很好维护…… 但又要求连通块?所以用并查集来维护…… 大概就是让并查集的fa和Treap的根是同一个节点吧…… TLE了N多发,可能是 ...

  3. json封装与解析

    #include <iostream> #include <boost/property_tree/ptree.hpp> #include <boost/property ...

  4. hdu 2940

    简单的大数乘法,直接改16进制~~ #include <cstdio> #include <cstdlib> #include <cmath> #include & ...

  5. NGUI Tutorial 3

    一. Create a Button 一.(Menu)NGUI -> Create -> Sprite 二.attach box colider to the Sprite , then ...

  6. VS2010 MFC DataGrid绑定实例

    VS2010环境下MFC使用DataGrid绑定数据源 参考:http://blog.csdn.net/fddqfddq/article/details/7874706 详细介绍如何在MFC中使用Da ...

  7. JDK8 学习

    http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

  8. ibatis框架的sqlmapclient接口

    SqlMapClient,是iBatis中的重要接口,这个接口涉及到对SQL映射的执行和批处理. 现在,就先了解它的对query开头方法的定义. 首先是 queryForList 方法: //指定SQ ...

  9. Xamarin.Android 入门之:Android的生命周期

    一.前言 活动是Android应用程序的基本构建块,他们可以在许多不同的状态存在.当你把一个Android程序置于后台,过一段时间再打开发现之前的数据还存在. 二.活动状态 下面的图表说明了一个活动可 ...

  10. Winsock完成端口模型-Delphi代码

    原文出处 <Windows网络编程技术>第8章 完成端口模型 由于原书附的是C代码,我把其翻译成Delphi代码. 其中winsock2.pas在delphi中不带,要另外下载http:/ ...