一个n个点的图,标号0 ~ n-1,第i个点向2 * i和2 * i + 1连边,构造哈密顿回路。
首先发现n为奇数无解。考虑转换为欧拉回路,将2 * i 与2 * i + 1合并为一点,这样点就转化为边了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define Rep(i, x, y) for (int i = x; i <= y; i ++)
#define Dwn(i, x, y) for (int i = x; i >= y; i --)
#define RepE(i, x) for(int i = pos[x]; i; i = g[i].nex)
using namespace std;
typedef long long LL;
const int N = 200005;
struct Edge { int x, y, z, nex; } g[N * 2];
int n, m, pos[N], sz, p[N], ans[N], az; bool vis[N];
void Init(int x, int y, int z) { g[++ sz] = (Edge) { x, y, z, pos[x] }, pos[x] = sz; }
void Dfs(int x) {
RepE(i, x) if (!vis[i]) {
vis[i] = 1, Dfs(g[i].y), p[++ m] = i;
}
}
int main()
{
scanf ("%d", &n);
if (n % 2) { puts("-1"); return 0; }
Rep(i, 0, n / 2 - 1) Init(i, ((i * 4 % n) / 2 + 1) % (n/2), 1), Init(i, (i * 4 % n) / 2, 0);
Dfs(0);
Dwn(i0, m, 1) {
int i = p[i0], x = g[i].x, y = g[i].y;
ans[++ az] = 2 * x + g[i].z;
}
Rep(i, 1, az) printf("%d ", ans[i]);
puts("0");
return 0;
}