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-1263
水果 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submissi ...
- ElasticSearch基础之映射mapping
[01]什么是mapping? 首先去看看官方文档,非常重要:https://www.elastic.co/guide/en/elasticsearch/reference/current/mappi ...
- 转载 关于启用HTTPS的一些经验分享
本文转载自 https://imququ.com/post/sth-about-switch-to-https.html 随着国内网络环境的持续恶化,各种篡改和劫持层出不穷,越来越多的网站选择了全站 ...
- 【剑指Offer学习】【面试题66:矩阵中的路径】
题目:请设计一个函数,用来推断在一个矩阵中是否存在一条包括某字符串全部字符的路径.路径能够从矩阵中随意一格開始.每一步能够在矩阵中间向左.右.上.下移动一格.假设一条路径经过了矩阵的某一格,那么该路径 ...
- Linux which 查找命令
在学习 兄弟连 linux教学视频 的时候,我将所学的 linux 命令记录在我的博客中,方便自己查阅. 权限管理命令: which 基础的命令 命令名称:which 命令的所在路径:/usr/bin ...
- Android之打包签名
一.什么的是打包? 打包就是根据签名和其他标识生成安装包. 二.什么是签名? 1.在android应用文件(apk)中保存的一个特别字符串 2.用来标识不同的应用开发者:开发者A,开发者B 3.一个应 ...
- Codeforces 749C【模拟】
FST的时候好像挂了挺多人的~ 其实思路没啥难的,就是更好地理解题意吧,1到n一直循环,直到没有人能vote,一个人能vote也能叉掉一个人,一个人被叉就不能vote,判谁赢. 其实我管vote干嘛, ...
- ACM心理过程
ACM 都已经一个学期过去了,然后还是很菜很菜,比起别人真的是差到一种境界好么???因为自身的太多原因,因为学的不够精,因为懒惰,因为学习的方法,因为自身对未来的不渴望.因为自满,因为自己的自甘堕落, ...
- bzoj 2406: 矩阵【二分+有源汇上下界可行流】
最大值最小,所以考虑二分 |Σaij-Σbij|<=mid,所以Σbij的上下界就是(Σaij-mid,Σaij+mid) 考虑建有上下界网络,连接(s,i,Σaik-mid,Σaik+mid) ...
- ueditor单独调用图片上传
很多人在问ueditor,如何单独使用图片上传功能,但是网上没有一篇能用的文档,没办法,我刚好也需要这个功能,花了3天时间(本人水平太菜,哎)终于知道怎么处理了,发出来给大家共享: 效果如下: 页面效 ...