uva10735 Euler Circuit
题外话:很多混合图问题可以转化为有向图问题(将无向边拆为两条有向边)
本题不行,因为只能经过一次
这种问题能想到网络流。。
复习欧拉回路:入度==出度
和uva1380有点相似,要先给无向边定向。原图为G,定向的边单独组成另一个G’
定向后对任意点,入度==出度,则有了回路。
否则调整原来的无向边。 (如果入度出度奇偶性不同,则无解)
出度增加(in-out/2)。
注意U->V变成V->U,U出度-1,V出度+1. 就像在运送”出度”,就是网络流。(满足out>in的点能提供出度) (可以提供的出度为diff[i]/2,需要接受的出度为-diff[i]/2)
原有的边cap为1(只能改一次方向)
设立超级节点S,T,S连可以提供的节点,cap为可以提供的出度
T类似。
当sum可以提供的出度!=MaxFlow,就无解。否则有解(必须提供出去。这里可以证明提供出去后所有的点in==out)
char dir[9];
scanf("%d%d%s", &u[i], &v[i], dir); 0 1 D
感觉可以做一个处理输入的专题了...
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std; const int INF = ; struct Edge {
int from, to, cap, flow;
Edge(int u, int v, int c, int f):from(u),to(v),cap(c),flow(f) {}
}; const int maxn = +; struct EdmondsKarp {
int n, m;
vector<Edge> edges; // 边数的两倍
vector<int> G[maxn]; // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
int a[maxn]; // 当起点到i的可改进量
int p[maxn]; // 最短路树上p的入弧编号 void init(int 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, , ));
m = edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} int Maxflow(int s, int t) {
int flow = ;
for(;;) {
memset(a, , sizeof(a));
queue<int> Q;
Q.push(s);
a[s] = INF;
while(!Q.empty()) {
int x = Q.front(); Q.pop();
for(int i = ; i < G[x].size(); i++) {
Edge& e = edges[G[x][i]];
if(!a[e.to] && e.cap > e.flow) {
p[e.to] = G[x][i];
a[e.to] = min(a[x], e.cap-e.flow);
Q.push(e.to);
}
}
if(a[t]) break;
}
if(!a[t]) break;
for(int u = t; u != s; u = edges[p[u]].from) {
edges[p[u]].flow += a[t];
edges[p[u]^].flow -= a[t];
}
flow += a[t];
}
return flow;
}
}; EdmondsKarp g; const int maxm = + ; int n, m, u[maxm], v[maxm], directed[maxm], id[maxm], diff[maxn]; vector<int> G[maxn];
vector<int> vis[maxn];
vector<int> path; void euler(int u) {
for(int i = ; i < G[u].size(); i++)
if(!vis[u][i]) {
vis[u][i] = ;
euler(G[u][i]);
path.push_back(G[u][i]+);
}
} void print_answer() {
// build the new graph
for(int i = ; i < n; i++) { G[i].clear(); vis[i].clear(); }
for(int i = ; i < m; i++) {
bool rev = false;
if(!directed[i] && g.edges[id[i]].flow > ) //id记录了无向边在edges中的位置
rev = true; //G记录边的起点对应的终点
if(!rev) //没有变反向
{ G[u[i]].push_back(v[i]);
vis[u[i]].push_back();
}
else {
G[v[i]].push_back(u[i]);
vis[v[i]].push_back();
}
} // print euler tour
path.clear();
euler(); //因为节点一记为了0 printf("");
for(int i = path.size()-; i >= ; i--) printf(" %d", path[i]);
printf("\n");
} int main() {
int T;
scanf("%d", &T); while(T--) {
scanf("%d%d", &n, &m);
g.init(n+); memset(diff, , sizeof(diff));
for(int i = ; i < m; i++) {
char dir[];
scanf("%d%d%s", &u[i], &v[i], dir);
u[i]--;
v[i]--;
directed[i] = (dir[] == 'D' ? : );
diff[u[i]]++; //出度-入度
diff[v[i]]--;
if(!directed[i]) { id[i] = g.edges.size(); g.AddEdge(u[i], v[i], ); }
} bool ok = true;
for(int i = ; i < n; i++)
if(diff[i] % != ) { ok = false; break; } int s = n, t = n+;
if(ok) {
int sum = ;
for(int i = ; i < n; i++) { if(diff[i] > ) {
g.AddEdge(s, i, diff[i]/);
sum += diff[i]/;
} if(diff[i] < ) {
g.AddEdge(i, t, -diff[i]/); }
} if(g.Maxflow(s, t) != sum)
ok = false;
} if(!ok)
printf("No euler circuit exist\n");
else
print_answer(); // underlying graph is always connected if(T)
printf("\n");
}
return ;
}
uva10735 Euler Circuit的更多相关文章
- 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( ...
- POJ2284 That Nice Euler Circuit (欧拉公式)(计算几何 线段相交问题)
That Nice Euler Circuit Time Limit: 3000MS M ...
- UVa 10735 (混合图的欧拉回路) Euler Circuit
题意: 给出一个图,有的边是有向边,有的是无向边.试找出一条欧拉回路. 分析: 按照往常的思维,遇到混合图,我们一般会把无向边拆成两条方向相反的有向边. 但是在这里却行不通了,因为拆成两条有向边的话, ...
- UVA 10735 Euler Circuit 混合图的欧拉回路(最大流,fluery算法)
题意:给一个图,图中有部分是向边,部分是无向边,要求判断是否存在欧拉回路,若存在,输出路径. 分析:欧拉回路的定义是,从某个点出发,每条边经过一次之后恰好回到出发点. 无向边同样只能走一次,只是不限制 ...
- Uva 1342 - That Nice Euler Circuit
Little Joey invented a scrabble machine that he called Euler, after the great mathematician. In his ...
- UVALive - 3263 That Nice Euler Circuit (几何)
UVALive - 3263 That Nice Euler Circuit (几何) ACM 题目地址: UVALive - 3263 That Nice Euler Circuit 题意: 给 ...
- Euler Circuit UVA - 10735(混合图输出路径)
就是求混合图是否存在欧拉回路 如果存在则输出一组路径 (我就说嘛 咱的代码怎么可能错.....最后的输出格式竟然w了一天 我都没发现) 解析: 对于无向边定向建边放到网络流图中add(u, v, 1) ...
- That Nice Euler Circuit(LA3263+几何)
That Nice Euler Circuit Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu D ...
随机推荐
- 六个优雅的 Linux 命令行技巧
一些非常有用的命令能让命令行的生活更满足,使用 Linux 命令工作可以获得许多乐趣,但是如果您使用一些命令,它们可以减少您的工作或以有趣的方式显示信息时,您将获得更多的乐趣.在今天的文章中,我们将介 ...
- unittest参数化parameterized
参考文章: https://www.cnblogs.com/royfans/p/7226360.html https://blog.csdn.net/zha6476003/article/detail ...
- absolute属性与IE6/IE7之间的误会
三.absolute属性与IE6/IE7之间的误会 absolute属性确实存在不少兼容性的问题,首先absolute属性定位相关(left/top)的些bug(例如IE6的奇偶bug)这里不予以讨论 ...
- scp.sh
#!/bin/sh #Auto change server files #liudong 2016-3-21 if [ ! -f ip.txt ];then echo -e "\033[31 ...
- bzoj2384
树状数组+KMP 匹配问题上KMP 但是问题在于如何判断两个位置相等,我们认为如果一个位置之前比他小的数数量相同那么就是相等. 那么我们用树状数组动态维护这个东西,每次跳nxt的时候用树状数组删除数. ...
- 用deamon打开ISO文件,提示命令行错误!!
用deamon打开ISO文件,提示命令行错误!! 解决方法:(没有关联iso文件)重新卸载deamon,再重新安装,在关联iso文件处打对勾,安装完成后即可用
- Entity Framework 实体间的外键关系
EF 默认是开户级联删除的,这此规则将会删除非空外键和多对多的关系,如果 在数据库上下文中的实体模型类 存在着 级联引用和多重删除路径,那么EF就抛出 级联引用和多重删除路径的异常. Introduc ...
- sublime text 3中修改tab键为缩进4个空格
1. 菜单栏里点击 Preferences-> Setting-User, 如图 2. 在弹出来的文本里,添加如下两行: { // 注意只有一个大括号,如果之前有属性,如在之前的属性后确保有 , ...
- 从ao神处偷取的头文件
#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long lo ...
- 自己动手搭建SSM
1.工具 apache-tomcat 7 apache-maven(后面详细讲!这东西我一开始也很懵逼) mysql 5以上的版本 navicat(有了这个就不用cmd了,可以直接显示数据库,如下图, ...