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( ...
随机推荐
- HDOJ-2045
不容易系列之(3)—— LELE的RPG难题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/O ...
- Flutter实战视频-移动电商-30.列表页_商品列表UI界面布局
30.列表页_商品列表UI界面布局 小程序里面的布局方式 小程序的图片上这里使用的是warp布局,因为首页里面火爆专区,已经用过了warp来布局了. 所以这里我们没有必要再讲一遍,这里我们使用List ...
- Identity Server 4 原理和实战(完结)_为 MVC 客户端刷新 Token
服务端修改token的过期使劲为60秒 过期了 仍然还能获取到api1的资源 api1,设置每隔一分钟就验证token 并且要求token必须要有超时时间这个参数, 1分钟后提示超时,两边都是一分钟, ...
- ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 25. 过滤器
在MVC的请求管道 并不是 asp.net core的请求管道.所以说Filter是专用于MVC的 贯穿特性,横穿关注点.比如授权.日志 这里的Authorize其实就是一个Filter,主要用来授 ...
- 电商:html样式集合
1. <span class="big" style="text-decoration:line-through;">原价:¥{zlcms:art ...
- jQuery 生成随机字符
//获取长度为len的随机字母 //获取长度为len的随机字母 function zimu(len){ len = len || 1; var $chars = 'ABCDEFGHIJKLMNOPQR ...
- CvvImage在高级别的Opencv2.4.11下的配置以及错误解决办法。
由于高版本的OpenCV2.4.11里取消了CImage(CvvImage),在此我们可以用老的版本替代. 在需要的地方引入 #include "CvvImage.h" 就可以用了 ...
- hdoj5493【树状数组+二分】
题意: 给你n个人的高度, 再给出一个值代表该高度下有前面比他高的 或 后面比他高的人数, 求满足条件下的最小字典序, 不行的话输出"impossible" 思路: 对于最小字典序 ...
- HTTP1.1规范下载 6个文档组成
- log日志中不打印异常栈的具体信息
问题与分析 最近在查项目的log时发现报了大量的NPE(NullPointerException),诡异的是只log了Exception的类名,却没有具体的堆栈信息,以致于无法对该NPE异常进行准确定 ...