欧拉图相关
判定
- 无向图欧拉路径 :仅仅存在两个点度数为奇数,其余为偶数
- 无向图欧拉回路 :度数均为偶数
图应该是连通的。
- 有向图欧拉路径 :存在两个点入度出度满足 1 / -1 的增量,其余相等
- 有向图欧拉回路 :入度 = 出度
需满足图是弱连通的。
注意度数为 \(0\) 的孤立点是可以存在的。
求解欧拉路径
ZR CSP七连 Day 7
给定二元组序列 \((A,B)\),要求构造排列,使得 \(A_{i} = A_{i+1}\) 或 \(B_{i} = B_{i+1}\) 成立,且 \(A_{i} = A_{i-1} = A_{i+1}\) 和 \(A_{i} = A_{i+1} = A_{i-1}\) 都不成立。 使得出现时间的字典序最小。\(n \le 10^5\)。
首先 \(A_{i} \to B_{i} + n\) 连无向边。
那么题目中就是要求就是求这个图的一个欧拉路径。
因为,第二个条件等价于无向边只能走一次。
如果存在两个度数为奇数的点,那么分别 dfs
求一遍
否则从 \(A_{1}, B_{1}\) 开始 dfs
。
然后呢,每次删除一条边,继续dfs。
#include <bits/stdc++.h>
#include <assert.h>
using namespace std;
#define fi first
#define se second
#define PII pair<int,int>
#define mp make_pair
#define ep emplace_back
typedef long long ll;
typedef double db;
inline int read(){
int x=0,v=1,ch=getchar();
while('0'>ch||ch>'9') {if(ch=='-')v=0;ch=getchar();}
while('0'<=ch&&ch<='9') {x=x*10+(ch&15);ch=getchar();}
return v?x:-x;
}
const int MAX = 1e6+5;
int n, a[MAX], b[MAX];
vector<PII>G[MAX];
int cur[MAX], ans[MAX], tmp[MAX] ;
int deg[MAX], vis[MAX];
void dfs(int x) {
for(int i = cur[x]; i < G[x].size(); i = cur[x] ) {
cur[x] = i + 1;
int y = G[x][i].fi;
if(!vis[y]) {
vis[y] = 1;
dfs(G[x][i].se);
ans[++ans[0]] = y;
}
}
}
void work(int x) {
memset(vis,0,sizeof(vis));
memset(cur,0,sizeof(cur));
ans[0] = 0;
dfs(x);
if(ans[0] < (n / 2)) {
puts("No");
exit(0);
}
for(int i=ans[0];i>0;--i) {
if(tmp[i] > ans[i] || tmp[i] == 0) {
swap(tmp, ans);
break;
}
if(tmp[i] < ans[i]) {
break;
}
}
}
signed main() {
n = read();
for(int i=1;i<=n;++i) {
a[i] = read();
b[i] = read() + n;
G[a[i]].ep(mp(i, b[i]));
G[b[i]].ep(mp(i, a[i]));
deg[a[i]] ++;
deg[b[i]] ++;
}
for(int i=1;i<=n+n;++i) sort(G[i].begin(), G[i].end());
int S = 1, cnt = 0;
for(int i=1;i<=n+n;++i) if(deg[i] & 1) ++ cnt;
if(cnt != 0 && cnt != 2) return puts("No"),0;
if(cnt == 0) {
work(a[1]);
work(b[1]);
}else {
for(int i=1;i<=n+n;++i) if(deg[i] & 1) work(i);
}
puts("Yes");
for(int i=n;i>=1;--i) printf("%d ",tmp[i]);
return 0;
}