John's Trip
无向欧拉回路 Hierholzer
正文
// 原题:https://oj.yecheng.tv/p/T1531
// 题意:多组无向图,每组给若干条街道(x,y,z,z 为街道编号),求从首条边两顶点中较小者出发、每条街道恰走一次的回路,输出街道编号序列(空格分隔、行末无空格);不存在则输出 Round trip does not exist.
// 思路:无向图欧拉回路。先判所有有度数顶点度数均为偶数且连通;再跑 Hierholzer,取边时按街道编号升序(与样例一致),记录所用街道编号,逆序即正序。
// 复杂度:O(E log E) 时间 / O(V+E) 空间
// 易错点:自环也占度数且必须用到;输出街道编号而非顶点;不存在时整句照抄含句点;多组各输出一行。
#include <bits/stdc++.h>
using namespace std;
int main(){
while(true){
vector<pair<int,int>> edges;
vector<int> zs;
int startv = -1;
bool any = false;
while(true){
int x, y;
if(!(cin>>x>>y)) return 0;
if(x==0 && y==0) break;
any = true;
if(startv==-1) startv = min(x,y);
int z;
cin>>z;
edges.push_back({x,y});
zs.push_back(z);
}
if(!any) break;
int M = edges.size();
map<int,int> deg;
for(int i=0;i<M;i++){ deg[edges[i].first]++; deg[edges[i].second]++; }
bool ok = true;
for(auto& kv: deg) if(kv.second%2!=0) ok=false;
if(ok){
map<int,int> fa;
for(auto& kv: deg) fa[kv.first]=kv.first;
function<int(int)> find=[&](int x){return fa[x]==x?x:fa[x]=find(fa[x]);};
for(int i=0;i<M;i++){
int a=find(edges[i].first), b=find(edges[i].second);
if(a!=b) fa[a]=b;
}
int root=-1;
for(auto& kv: deg){
int r=find(kv.first);
if(root==-1) root=r;
else if(root!=r) ok=false;
}
}
if(!ok){
cout<<"Round trip does not exist.\n";
continue;
}
map<int,vector<int>> adj;
for(int i=0;i<M;i++){
adj[edges[i].first].push_back(i);
adj[edges[i].second].push_back(i);
}
for(auto& kv: adj) sort(kv.second.begin(), kv.second.end(), [&](int a,int b){return zs[a]<zs[b];});
map<int,vector<int>> pos;
for(auto& kv: adj) for(int i=0;i<(int)kv.second.size();i++) pos[kv.first].push_back(i);
vector<bool> used(M,false);
vector<int> circuit;
function<void(int)> dfs=[&](int v){
while(true){
int e=-1;
for(int i=0;i<(int)adj[v].size();i++){
int idx=adj[v][i];
if(!used[idx]){ e=idx; break; }
}
if(e==-1) break;
used[e]=true;
int u=(edges[e].first==v)?edges[e].second:edges[e].first;
dfs(u);
circuit.push_back(zs[e]);
}
};
dfs(startv);
reverse(circuit.begin(), circuit.end());
for(int i=0;i<(int)circuit.size();i++){
if(i) cout<<' ';
cout<<circuit[i];
}
cout<<"\n";
}
return 0;
}
一本通·提高篇的其它内容
- 活动安排
- 种树
- 喷水装置
- 加工生产调度
- 智力大冲浪
- 数列极差
- 数列分段
- 线段
- 家庭作业
- 钓鱼
- 糖果传递
- 愤怒的牛
- Best Cow Fences
- 曲线
- 数列分段 II
- 扩散
- 灯泡
- 传送带
- 数的划分
- 生日蛋糕
- 小木棍
- Addition Chains
- 埃及分数
- 平板涂色
- 质数方阵
- 靶形数独
- 电路维修
- 魔板
- Knight Moves
- 棋盘游戏
- Keyboarding
- 移动玩具
- 山峰和山谷
- Oulipo
- 图书管理
- Power Strings
- Seekthe Name, Seek the Fame
- Friends
- A Horrible Poem
- Beads
- Antisymmetry
- 门票
- 收集雪花
- 剪花布条
- Power Strings
- Radio Transmission
- OKR-Periods of Words
- 似乎在梦中见过的样子
- Censoring
- Phone List
- The XOR Largest Pair
- Nikitosh 和异或
- Immediate Decodability
- L 语言
- Secret Message 秘密信息
- 背单词
- The Xor-longest Path
- Keywords Search
- 玄武密码
- Censoring