UVA 10735 Euler Circuit (最大流)
题意:求混合图的欧拉路径。
一句话总结:网络流,最主要在于建图,此题是将出度则是和流量联系在了一起,用最大流来调整边的指向。
分析:
这题的困难之处在于无向边只能用一次,相当于一个方向未定的有向边。
首先用并查集判断图的连通性,(直接计数O(1),做1395 Slim Span学到的技巧)。
我们知道有向图的欧拉路径存在的充要条件是最多两个点的入度不等于出度,而且相差为1。这题要求回路,只需要所有点的入度等于出度就行了。
对于无向边,一开始可以随意确定一个方向。这样不能保证所有点的入度等于出度,但是可以想办法调整。
比如说u->v,那么如果改变方向的话,就相当于把一个出度运输给了v。
这让人联想到了网络流,一条无向边就对应着一条容量为1的边,建图的时候就把u在v直接连一条容量为1的边。
那么剩下的就是决定怎么运输?运输多少?我们的目标是调整使得所有的点入度等于出度。
因为每次调整入度和出度的差改变都为偶,那么如果有入度和出度相差为奇数的点,那么一定是不满足条件的。
下面只考虑度数差为偶的点,对于入度大于出度的点,那么这个点需要出度,需要(in[u]-out[u])/2个出度,那么就把它和汇点连一条相应容量的边。
对于出度大的点类似处理。跑网络流,进行调整。根据残流网络,可以得出边的指向。在跑Euler路径就行了。
#include<bits/stdc++.h>
using namespace std; int V,E;
const int maxv = ;
#define PB push_back vector<int> D[maxv]; int in[maxv],out[maxv]; struct Edge
{
int v,cap;
}; vector<Edge> edges;
vector<int> G[maxv];
int S,T;
int vcnt;
void AddEdge(int u,int v,int c)
{
G[u].PB(edges.size());
edges.PB({v,c});
G[v].PB(edges.size());
edges.PB({u,});
} int lv[maxv];
int q[maxv]; bool bfs()
{
memset(lv,,sizeof(int)*(vcnt));
int l = , r = ;
q[r++] = S; lv[S] = ;
while(r>l){
int u = q[l++];
for(int i = ; i < G[u].size(); i++){
Edge &e = edges[G[u][i]];
if(!lv[e.v] && e.cap){
lv[e.v] = lv[u]+;
q[r++] = e.v;
}
}
}
return lv[T];
} int cur[maxv];
int dfs(int u,int a)
{
if(u == T||!a) return a;
int flow = ,f;
for(int &i = cur[u]; i < G[u].size(); i++){
Edge &e = edges[G[u][i]];
if(lv[e.v] == lv[u]+ && (f = dfs(e.v,min(e.cap,a)))){
flow += f;
a -= f;
e.cap -= f;
edges[G[u][i]^].cap+=f;
if(!a) break;
}
}
return flow;
} const int INF = 0x3f3f3f3f;
int MaxFlow()
{
int flow = ;
while(bfs()){
memset(cur,,sizeof(int)*(vcnt));
flow += dfs(S,INF);
}
return flow;
} int build()
{
int del = ;
for(int i = ; i <= V; i++){
int d;
if((in[i]+out[i])&) return -;
if(out[i]<in[i]) {
d = (in[i]-out[i])>>; del+=d; AddEdge(i,T,d);
}else if(in[i]<out[i]){
d = (out[i]-in[i])>>;
AddEdge(S,i,d);
}
}
return del;
} int pa[maxv];
int Find(int x) { return x == pa[x]?x:pa[x]=Find(pa[x]); }
bool vis[maxv];
int cnt; void init()
{
S = ; T = V+; vcnt = T+;
for(int i = ; i <= V; i++) D[i].clear(),in[i]=out[i]=;
edges.clear();
for(int i = ; i <= T; i++) G[i].clear();
for(int i = ; i <= V; i++) pa[i] = i;
memset(vis,,sizeof(bool)*vcnt);
cnt = ;
} bool read()
{
scanf("%d%d",&V,&E);
init();
for(int i = ; i < E; i++){
char ch;
int u,v; scanf("%d %d %c",&u,&v,&ch);
if(ch == 'U'){
AddEdge(u,v,);
}else {
D[u].PB(v);
}
if(!vis[u]) cnt++,vis[u] = true;
if(!vis[v]) cnt++,vis[v] = true;
int s1 = Find(u),s2 = Find(v);
if(s1 != s2) {
cnt--;
pa[s1] = s2;
}
out[u]++; in[v]++;
}
return cnt == ;
} void reBuild()
{
for(int u = ; u <= V; u++){
for(int i = ; i < G[u].size(); i++){
Edge &e = edges[G[u][i]];
if(e.cap) {
int v0 = edges[G[u][i]^].v, v1 = e.v;
if(v0&&v0<=V&&v1&&v1<=V) D[v0].PB(v1);
}
}
}
} stack<int> ans;
void Euler(int u)
{
for(int &i = cur[u]; i < D[u].size();){
int v = D[u][i++];
Euler(v);
//printf("%d ",v);
ans.push(v);
}
} void solve()
{
if(read()) {
int totFlow = build();
if(~totFlow && totFlow <= MaxFlow()) {
reBuild();
memset(cur,,sizeof(int)*(vcnt));
Euler();
printf("");
while(ans.size()){
printf(" %d",ans.top());
ans.pop();
}
putchar('\n');
return;
}
}
puts("No euler circuit exist");
} int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int Test; scanf("%d",&Test); while(Test--){
solve();
if(Test) putchar('\n');
}
return ;
}
PS:
欧拉路径输出的套圈算法,进行了一点小小的优化,从dinic中收到启发改成了用数组cur[],这样可以节省判断vis的时间。
还有一个问题,此题是SJ,如下直接在dfs里逆序输出就WA。。。保存答案stack里输出才A,这样写有什么trick的情况吗?
void Euler(int u)
{
for(int &i = cur[u]; i < D[u].size();){
int v = D[u][i++];
Euler(v);
printf("%d ",v);
}
} 调用
memset(cur,,sizeof(int)*(vcnt));
Euler();
printf("1\n");
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) ...
- 紫书 例题 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 ...
- UVA-10735 - Euler Circuit(混合欧拉回路输出)
题意:给你一个图,有N个点,M条边,这M条边有的是单向的,有的是双向的. 问你能否找出一条欧拉回路,使得每条边都只经过一次! 分析: 下面转自别人的题解: 把该图的无向边随便定向,然后计算每个点的入度 ...
- poj2284 That Nice Euler Circuit(欧拉公式)
题目链接:poj2284 That Nice Euler Circuit 欧拉公式:如果G是一个阶为n,边数为m且含有r个区域的连通平面图,则有恒等式:n-m+r=2. 欧拉公式的推广: 对于具有k( ...
随机推荐
- PXE与cobbler实现系统自动安装
安装操作系统的流程事实上并不复杂,如果你要给三五台服务器安装系统那么我们手工去安装即可.但是当我们要部署的是大型机房的操作系统的时候显然手动安装去一台一台的点,是不现实的.尤其现在互联网行业高速发展, ...
- 如何实现Vue已经弃用的$dispatch和$broadcast方法?
对于父子(含跨级)传递数据的通信方式,Vue.js 并没有提供原生的 API 来支持,而是推荐使用大型数据状态管理工具 Vuex,但 Vuex 对于小型项目来说用起来真的很麻烦. 在 Vue.js 1 ...
- Two sum(给定一个无重复数组和目标值,查找数组中和为目标值的两个数,并输出其下标)
示例: nums = [1,2,5,7] target = [6] return [0,2] Python解决方案1: def twoSum(nums, target): ""&q ...
- 无法打开包括文件:“SDKDDKVer.h”: No such file or directory
在已经装有Visual Studio 2010的系统中,同时安装Visual Studio 2012,安装过程很顺利,但到使用VS2013时,却出问题了. 本文主要介绍:VS中新建工程编译时出现,“无 ...
- Codeforces325 D【并查集维护连通性】
参考:大牛blog 思路: 因为是环,所以可以复制一下图,先判断一下和他是不是和与他相邻的8个之一的一个障碍使得构成了一个环,环就是一个连通,用并查集维护即可: 如果没有就ans++,然后并把这个点加 ...
- [Xcode 实际操作]二、视图与手势-(4)给图像视图添加边框效果
目录:[Swift]Xcode实际操作 本文将演示给图片添加颜色相框 import UIKit class ViewController: UIViewController { override fu ...
- [Swift]堆栈Stack:检索最小元素时间复杂度O(1)
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- IT兄弟连 JavaWeb教程 EL表达式中的内置对象
EL语言定义了11个隐含对象,它们都是java.util.Map类型,网页制作者可通过它们来便捷地访问Web应用中的特定数据.表1对这11个隐含对象做了说明. 1 EL表达式中的内置对象 这11个隐 ...
- LVS 负载均衡器总结
下面部分原理部分,是从网上摘录,源网址已经无从获取,我将其中一小部分模糊的说明加入了一些自己的理解,仅最大可能让全文容易阅读,也方便自己以后参考,若你是大牛希望能给我一些宝贵的建议,将理解有误的地方加 ...
- SpringBlade 2.0-RC3 发布,全新的微服务开发平台
经过了十天的艰苦奋斗,SpringBlade 2.0-RC3发布了,此版本增加了很多有用的功能,距离正式版本更近一步! SpringBlade简介: SpringBlade 2.0 是一个基于 Spr ...