题目链接点这儿
就是给一张无向图,让你求一个从起点遍历所有点返回起点的路径,这里路径不能重复使用(只有2个点时可以重复一次。。因为不重复它回不去啊。。。)
所以就是一个求Hamilton回路的题
由于题中给出了,对每个点,都至少有(n+1)/2个点与之相邻。很明显,这个条件下肯定满足ore定理。从而肯定可以构造出解。(所以题中说可以输出"No solution"的地方就是纯属卖萌了╮( ̄▽ ̄")╭ )
ore定理如下图(组合数学第5版)
构造解的方案如下图(依然来自组合数学第5版(组数真是好东西))
组合数学上给出的方案很清晰,只要实现了书上的过程就完成了Hamilton回路的构造。
当然这个题有个地方要注意,那就是最后输出的时候肯定是1打头的(由于题目条件的限制),所以要注意不要直接从自己构造的回路的head处输出(其实。。。最后构造的是一个圈。。。无所谓head和tail了。。)
代码如下。。略长。。。不过是严格按照书上的过程实现的。
#include <bits/stdc++.h> #define max(a,b) ((a)>(b))?(a):(b) #define min(a,b) ((a)>(b))?(b):(a) #define rep(i,initial_n,end_n) for(int (i)=(initial_n);(i)<(end_n);i++) #define repp(i,initial_n,end_n) for(int (i)=(initial_n);(i)<=(end_n);(i)++) #define eps 1.0E-8 #define MAX_N 1010 #define INF 1 << 30 using namespace std; typedef pair<int, int> pii; typedef pair<double, double> pdd; typedef long long ll; typedef unsigned long long ull; bool atlas[1001][1001] = { { false } }, used[1001] = { false }; int next[1001], len = 1, head = 1, tail, n; void dfs(int now); void extent(); void reverse(int start, int stop); void creat_loop(); int main() { int tmp; scanf("%d", &n); getchar(); repp(i, 1, n) { while(true) { scanf("%d", &tmp); atlas[i][tmp] = atlas[tmp][i] = true; tmp = getchar(); if(tmp =='\n' || tmp==EOF || tmp == '\r') break; } } used[1] = true; dfs(1); while(len < n) { if(!atlas[head][tail]) creat_loop(); extent(); } if(!atlas[head][tail]) creat_loop(); tmp = 1; while(n--) { printf("%d ", tmp); tmp = next[tmp]; } puts("1"); return 0; } void dfs(int now) { repp(i, 1, n) { if(!used[i] && atlas[now][i]) { len++; tail = next[now] = i; used[i] = true; if(len == n) return ; dfs(i); return ; } } } void extent() { int tmp = head, before; repp(i, 1, n) if(!used[i] && atlas[i][tmp]) { len++; next[i] = tmp; head = i; used[i] = true; return ; } while(true) { before = tmp, tmp = next[tmp]; repp(i, 1, n) { if(!used[i] && atlas[tmp][i]) { len++; used[i] = true; next[tail] = head; next[i] = tmp; head = i; tail = before; return ; } } } } void creat_loop() { int before = next[head], tmp = next[before]; while(true) { if(atlas[before][tail] && atlas[tmp][head]) { reverse(tmp, tail); next[tmp] = head; head = tail; tail = before; next[tail] = head; return ; } before = tmp, tmp = next[tmp]; } } void reverse(int start, int stop) { int to = start, from = next[start], tmp; while(to != stop) { tmp = next[from]; next[from] = to; to = from; from = tmp; } }