UVA-10735 - Euler Circuit(混合欧拉回路输出)
题意:给你一个图,有N个点,M条边,这M条边有的是单向的,有的是双向的.
问你能否找出一条欧拉回路,使得每条边都只经过一次!
分析:
下面转自别人的题解:
把该图的无向边随便定向,然后计算每个点的入度和出度。如果有某个点出入度之差为奇数,那么肯定不存在欧拉回路。因为欧拉回路要求每点入度 = 出度,也就是总度数为偶数,存在奇数度点必不能有欧拉回路。
好了,现在每个点入度和出度之差均为偶数。那么将这个偶数除以2,得x。也就是说,对于每一个点,只要将x条边改变方向(入>出就是变入,出>入就是变出),就能保证出 = 入。如果每个点都是出 = 入,那么很明显,该图就存在欧拉回路。
现在的问题就变成了:我该改变哪些边,可以让每个点出 = 入?构造网络流模型。首先,有向边是不能改变方向的,要之无用,删。一开始不是把无向边定向了吗?定的是什么向,就把网络构建成什么样,边长容量上限1。另新建s和t。对于入 > 出的点u,连接边(u, t)、容量为x,对于出 > 入的点v,连接边(s, v),容量为x(注意对不同的点x不同)。之后,察看是否有满流的分配。有就是能有欧拉回路,没有就是没有。欧拉回路是哪个?察看流值分配,将所有流量非 0(上限是1,流值不是0就是1)的边反向,就能得到每点入度 = 出度的欧拉图。
由于是满流,所以每个入 > 出的点,都有x条边进来,将这些进来的边反向,OK,入 = 出了。对于出 > 入的点亦然。那么,没和s、t连接的点怎么办?和s连接的条件是出 > 入,和t连接的条件是入 > 出,那么这个既没和s也没和t连接的点,自然早在开始就已经满足入 = 出了。那么在网络流过程中,这些点属于“中间点”。我们知道中间点流量不允许有累积的,这样,进去多少就出来多少,反向之后,自然仍保持平衡。
所以,就这样,混合图欧拉回路问题,解了。
// File Name: 10735.cpp
// Author: Zlbing
// Created Time: 2013/6/18 21:46:23 #include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define LL long long
#define REP(i,r,n) for(int i=r;i<=n;i++)
#define RREP(i,n,r) for(int i=n;i>=r;i--)
const int MAXN=;
int n,m;
struct Edge2{
int from,to;
};
vector<Edge2> edges2;
vector<int> G2[MAXN];
struct Edge{
int from,to,cap,flow;
};
bool cmp(const Edge& a,const Edge& b){
return a.from < b.from || (a.from == b.from && a.to < b.to);
}
struct Dinic{
int n,m,s,t;
vector<Edge> edges;
vector<int> G[MAXN];
bool vis[MAXN];
int d[MAXN];
int cur[MAXN];
void init(int n){
this->n=n;
for(int i=;i<=n;i++)G[i].clear();
edges.clear();
}
void AddEdge(int from,int to,int cap){
edges.push_back((Edge){from,to,cap,});
edges.push_back((Edge){to,from,,});//当是无向图时,反向边容量也是cap,有向边时,反向边容量是0
m=edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
}
bool BFS(){
CL(vis,);
queue<int> Q;
Q.push(s);
d[s]=;
vis[s]=;
while(!Q.empty()){
int x=Q.front();
Q.pop();
for(int i=;i<G[x].size();i++){
Edge& e=edges[G[x][i]];
if(!vis[e.to]&&e.cap>e.flow){
vis[e.to]=;
d[e.to]=d[x]+;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x,int a){
if(x==t||a==)return a;
int flow=,f;
for(int& i=cur[x];i<G[x].size();i++){
Edge& e=edges[G[x][i]];
if(d[x]+==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>){
e.flow+=f;
edges[G[x][i]^].flow-=f;
flow+=f;
a-=f;
if(a==)break;
}
}
return flow;
}
//当所求流量大于need时就退出,降低时间
int Maxflow(int s,int t,int need){
this->s=s;this->t=t;
int flow=;
while(BFS()){
CL(cur,);
flow+=DFS(s,INF);
if(flow>need)return flow;
}
return flow;
}
//最小割割边
vector<int> Mincut(){
BFS();
vector<int> ans;
for(int i=;i<edges.size();i++){
Edge& e=edges[i];
if(vis[e.from]&&!vis[e.to]&&e.cap>)ans.push_back(i);
}
return ans;
}
void Reduce(){
for(int i = ; i < edges.size(); i++) edges[i].cap -= edges[i].flow;
}
void ClearFlow(){
for(int i = ; i < edges.size(); i++) edges[i].flow = ;
}
}; Dinic solver;
int in[MAXN],out[MAXN];
stack<int> S;
int vis[MAXN*MAXN];
void build()
{
for(int i=;i<solver.edges.size();i++)
{
Edge e=solver.edges[i];
if(e.from>=&&e.from<=n&&e.to>=&&e.to<=n&&e.cap>)
{
if(e.flow)
{
edges2.push_back((Edge2){e.to,e.from});
int mm=edges2.size();
G2[e.to].push_back(mm-);
}
else
{
edges2.push_back((Edge2){e.from,e.to});
int mm=edges2.size();
G2[e.from].push_back(mm-);
}
}
}
}
void dfs(int u)
{
//printf("u=%d \n",u);
for(int i=;i<G2[u].size();i++)
{
int mm=G2[u][i];
Edge2 e=edges2[mm];
int v=e.to;
//printf("aau=%d v=%d\n",u,v);
if(!vis[mm])
{
//printf("u=%d v=%d\n",u,v);
vis[mm]=;
dfs(v);
}
}
S.push(u);
}
int main()
{
int T;
scanf("%d",&T);
for(int cas=;cas<=T;cas++)
{
scanf("%d%d",&n,&m);
solver.init(n+);
int s=,t=n+;
for(int i=;i<=n;i++)G2[i].clear();
edges2.clear();
CL(in,);
CL(out,);
int a,b;char c[];
for(int i=;i<m;i++)
{
scanf("%d%d%s",&a,&b,c);
if(c[]=='D'){
edges2.push_back((Edge2){a,b});
int mm=edges2.size();
G2[a].push_back(mm-);
in[b]++;out[a]++;
}
else if(c[]=='U')
{
solver.AddEdge(a,b,);
in[b]++;out[a]++;
}
}
bool flag=true;
for(int i=;i<=n;i++)
if(abs(in[i]-out[i])&)
{
flag=false;break;
}
if(!flag)
{
printf("No euler circuit exist\n");
if(cas!=T)printf("\n");
continue;
}
int sum=;
for(int i=;i<=n;i++)
{
if(in[i]>out[i])
{
solver.AddEdge(i,t,(in[i]-out[i])/);
}
else if(out[i]>in[i])
{
solver.AddEdge(s,i,(out[i]-in[i])/);
sum+=abs(in[i]-out[i])/;
}
}
// for(int i=0;i<solver.edges.size();i++)
// {
// printf("u==%d v==%d cap=%d\n",solver.edges[i].from,solver.edges[i].to,solver.edges[i].cap);
// }
if(sum!=solver.Maxflow(s,t,INF))
{
printf("No euler circuit exist\n");
if(cas!=T)printf("\n");
continue;
}
build();
//for(int i=0;i<edges2.size();i++)
//printf("from=%d to=%d\n",edges2[i].from,edges2[i].to);
while(!S.empty())S.pop();
CL(vis,);
dfs();
int first=;
while(!S.empty())
{
if(first)
printf(" ");
first++;
printf("%d",S.top());
S.pop();
}
printf("\n");
if(cas!=T)printf("\n");
}
return ;
}
UVA-10735 - Euler Circuit(混合欧拉回路输出)的更多相关文章
- UVA 10735 Euler Circuit 混合图的欧拉回路(最大流,fluery算法)
题意:给一个图,图中有部分是向边,部分是无向边,要求判断是否存在欧拉回路,若存在,输出路径. 分析:欧拉回路的定义是,从某个点出发,每条边经过一次之后恰好回到出发点. 无向边同样只能走一次,只是不限制 ...
- UVa 10735 - Euler Circuit(最大流 + 欧拉回路)
链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- UVA 10735 Euler Circuit (最大流)
题意:求混合图的欧拉路径. 一句话总结:网络流,最主要在于建图,此题是将出度则是和流量联系在了一起,用最大流来调整边的指向. 分析: 这题的困难之处在于无向边只能用一次,相当于一个方向未定的有向边. ...
- Euler Circuit UVA - 10735(混合图输出路径)
就是求混合图是否存在欧拉回路 如果存在则输出一组路径 (我就说嘛 咱的代码怎么可能错.....最后的输出格式竟然w了一天 我都没发现) 解析: 对于无向边定向建边放到网络流图中add(u, v, 1) ...
- UVa 10735 (混合图的欧拉回路) Euler Circuit
题意: 给出一个图,有的边是有向边,有的是无向边.试找出一条欧拉回路. 分析: 按照往常的思维,遇到混合图,我们一般会把无向边拆成两条方向相反的有向边. 但是在这里却行不通了,因为拆成两条有向边的话, ...
- 紫书 例题 11-13 UVa 10735(混合图的欧拉回路)(最大流)
这道题写了两个多小时-- 首先讲一下怎么建模 我们的目的是让所有点的出度等于入度 那么我们可以把点分为两部分, 一部分出度大于入度, 一部分入度大于出度 那么显然, 按照书里的思路,将边方向后,就相当 ...
- UVA LIVE-3263 - That Nice Euler Circuit
画一个顶点为偶数的封闭的二维图,当然.这个图能够自交,给出画的过程中的一些轨迹点.求出这个图把二次元分成了几部分,比如三角形把二次元分成了两部分. 这个的话,有图中顶点数+部分数-棱数=2的定律,这是 ...
- Uva 1342 - That Nice Euler Circuit
Little Joey invented a scrabble machine that he called Euler, after the great mathematician. In his ...
- 混合欧拉回路的判断(Dinic)
POJ1637 Sightseeing tour Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 7483 Accepte ...
随机推荐
- 配置Nginx 1.8支持PHP 5.6
启动PHP和Nginx 修改Nginx配置文件/usr/local/nginx/conf/nginx.conf server { listen ; server_name localhost; loc ...
- 如果 @s int 把它转成字符,可以这样 cast(@s as varchar)
如果 @s int 把它转成字符,可以这样 cast(@s as varchar)
- 关于this 的一个问题
var name = "the window"; var object = { name:"my object"; getName:function(){ re ...
- jquery生成UUID的方法
来源: http://www.broofa.com/2008/09/javascript-uuid-function/ 1.代码: http://www.broofa.com/Tools/Math ...
- jquery-动态设置ul li a链接目标
概述: 先上我的布局图: ul中的每一个li里面包含着一个'a'超链接,可以猜想到,我想没点击ul->li里面每个a,链接到不同的页面,在这里,我用iframe完成. html主要代码为: &l ...
- windows Server 2008 -必须使用“角色管理工具”安装或配置Microsoft .Net Framework 3.5
在windows Server 2008上安装 .Net Framework 3.5的时候,报错:必须使用“角色管理工具”安装或配置Microsoft .Net Framework 3.5. Solu ...
- SQLite 入门教程(四)增删改查,有讲究
增删改查操作,其中增删改操作被称为数据操作语言 DML,相对来说简单一点. 查操作相对来说复杂一点,涉及到很多子句,所以这篇先讲增删改操作,以例子为主,后面再讲查操作. 一.插入数据 INSERT I ...
- C# 通过hessian调Java注意事项
照理说C#可以通过标准的web服务可以轻松地调用Java,但是鉴于hessian的高性能及开发效率,个人认为C#通过hessian调用java是很值得提倡的.之前完成的一个比较大型的企业应用项目就是采 ...
- 对UIImage进行的一些操作
1.生成指定宽高的UIImage对象(oldImage为原始图片对象,newImage为操作后的图片对象) // 参数1:图片的尺寸 参数2:是否透明(没看出YES和NO有什么区别) 参数3:缩放(1 ...
- 通常我们使用[NSDate date]方法得到的时间与当前时间不一致,如何解决?
NSDate *date = [NSDate date]; NSTimeZone *zone = [NSTimeZone systemTimeZone]; NSInteger interv ...