164 lines
4.7 KiB
C++
164 lines
4.7 KiB
C++
/*
|
||
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;
|
||
} |