Files
python/TangDou/AcWing/EulerPath/CF36E.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

164 lines
4.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
https://codeforces.com/problemset/problem/36/E
欧拉路+并查集+思路~
简直要被绕晕了……有好多细节要注意……
首先,要分为只有一个联通块,有一个联通块和有两个及以上联通块,判断联通块数用并查集。
最后一种是不行的,直接输出-1。
对于其余两种,要判断每个点的入度是否满足欧拉路条件(没有奇点或有两个奇点),特别的,对于第二种,
每个连通块内要分别判断。
然后,如果有两个奇点,从其中一个出发遍历即可。
在第一种情况中,如果有0个或2个起点,则求出总的欧拉路后从任意处截断。
如果有4个起点,任选两个连边后求欧拉路,再在连的边处截断。
https://blog.csdn.net/xianpingping/article/details/82468730
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 10100
using namespace std;
struct abcd {
int to, num, next;
bool flag;
} table[M << 1];
int head[M], tot = 1;
int n = 10000, m, a[2], degree[M];
int stack[M], top;
void Add(int x, int y, int z) {
degree[y]++;
table[++tot].to = y;
table[tot].num = z;
table[tot].next = head[x];
head[x] = tot;
}
namespace Union_Find_Set {
int fa[M], rank[M];
int Find(int x) {
if (!fa[x] || fa[x] == x)
return fa[x] = x;
return fa[x] = Find(fa[x]);
}
void Union(int x, int y) {
x = Find(x);
y = Find(y);
if (x == y) return;
if (rank[x] > rank[y])
swap(x, y);
if (rank[x] == rank[y])
rank[y]++;
fa[x] = y;
}
} // namespace Union_Find_Set
void DFS(int x) {
int i;
for (i = head[x]; i; i = head[x]) {
head[x] = table[head[x]].next;
if (table[i].flag)
continue;
table[i ^ 1].flag = true;
DFS(table[i].to);
stack[++top] = table[i].num;
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("CF36E.in", "r", stdin);
#endif
using namespace Union_Find_Set;
int i, x, y;
cin >> m;
if (m == 1) {
cout << -1 << endl;
return 0;
}
for (i = 1; i <= m; i++) {
scanf("%d%d", &x, &y);
Add(x, y, i);
Add(y, x, i);
Union(x, y);
}
for (i = 1; i <= n; i++)
if (head[i]) {
if (!a[0])
a[0] = i;
else if (Find(i) != Find(a[0])) {
if (!a[1])
a[1] = i;
else if (Find(i) != Find(a[1]))
return cout << -1 << endl, 0;
}
}
if (a[1]) {
int cnt[2] = {0, 0};
int st[2] = {a[0], a[1]};
for (i = 1; i <= n; i++)
if (degree[i] & 1) {
cnt[Find(i) == Find(a[1])]++;
st[Find(i) == Find(a[1])] = i;
}
if (cnt[0] > 2 || cnt[1] > 2)
return cout << -1 << endl, 0;
DFS(st[0]);
cout << top << endl;
while (top)
printf("%d%c", stack[top], top == 1 ? '\n' : ' '), top--;
DFS(st[1]);
cout << top << endl;
while (top)
printf("%d%c", stack[top], top == 1 ? '\n' : ' '), top--;
} else {
int st[4] = {0, 0, 0, 0};
for (i = 1; i <= n; i++)
if (degree[i] & 1) {
if (!st[0])
st[0] = i;
else if (!st[1])
st[1] = i;
else if (!st[2])
st[2] = i;
else if (!st[3])
st[3] = i;
else
return cout << -1 << endl, 0;
}
if (!st[0]) {
DFS(a[0]);
cout << 1 << '\n'
<< stack[top--] << endl;
cout << top << endl;
while (top)
printf("%d%c", stack[top], top == 1 ? '\n' : ' '), top--;
} else if (!st[2]) {
DFS(st[0]);
cout << 1 << '\n'
<< stack[top--] << endl;
cout << top << endl;
while (top)
printf("%d%c", stack[top], top == 1 ? '\n' : ' '), top--;
} else {
Add(st[0], st[1], m + 1);
Add(st[1], st[0], m + 1);
DFS(st[2]);
for (i = 1; i <= top; i++)
if (stack[i] == m + 1)
break;
cout << top - i << endl;
while (top > i)
printf("%d%c", stack[top], top == i + 1 ? '\n' : ' '), top--;
top--;
cout << top << endl;
while (top)
printf("%d%c", stack[top], top == 1 ? '\n' : ' '), top--;
}
}
return 0;
}