题目链接:http://poj.org/problem?id=2438
本文链接:http://www.cnblogs.com/Ash-ly/p/5452615.html
题意:
有2*N个小朋友要坐在一张圆桌上吃饭,但是每两个小朋友之间存在一种关系,即敌人或者朋友,然后需要让你安排一个座位次序,使得相邻的两个小朋友都不会是敌人.假设每个人最多有N-1个敌人.如果没有输出"No solution!".
思路:
如果按照题意直接建图,每个点表示一个小朋友,小朋友之间的敌对关系表示两个点之间有边.问题是求小朋友围着桌子的座次就是求图中的一个环,但是要求这个环不能包含所给出的每条边,所有没给出的边却是可以用的,也就是说本题实际上是在上面建的图的反图上求解一个环,使得该环包含所有点.包含所有点的环一定是一条哈密顿回路,所以题目就是求所给图的反图上的一条哈密顿回路.
题目中给了一个特殊条件,就是一共有2*N个小朋友,但是每个人最多有N-1个敌人,也就是说,每个小朋友可以选择坐在身边的小朋友数大于n + 1,这就意味着在建立的反图中,每个点的度数大于N+1,由Dirac定理可知,此图一定存在哈密顿回路,所以答案不会出现"No solution!",即直接构造哈密顿回路就可以了.
代码:
1 #include <iostream> 2 #include <cmath> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <queue> 8 #include <stack> 9 #include <vector> 10 11 using namespace std; 12 typedef long long LL; 13 const int maxN = 400; 14 15 inline void reverse(int arv[maxN + 7], int s, int t){ 16 int temp; 17 while(s < t){ 18 temp = arv[s]; 19 arv[s] = arv[t]; 20 arv[t] = temp; 21 s++; 22 t--; 23 } 24 } 25 26 void Hamilton(int ans[maxN + 7], bool map[maxN + 7][maxN + 7], int n){ 27 int s = 1, t; 28 int ansi = 2; 29 int i, j; 30 int w; 31 int temp; 32 bool visit[maxN + 7] = {false}; 33 for(i = 1; i <= n; i++) if(map[s][i]) break; 34 t = i; 35 visit[s] = visit[t] = true; 36 ans[0] = s; 37 ans[1] = t; 38 while(true){ 39 while(true){ 40 for(i = 1; i <= n; i++){ 41 if(map[t][i] && !visit[i]){ 42 ans[ansi++] = i; 43 visit[i] = true; 44 t = i; 45 break; 46 } 47 } 48 if(i > n) break; 49 } 50 w = ansi - 1; 51 i = 0; 52 reverse(ans, i, w); 53 temp = s; 54 s = t; 55 t = temp; 56 while(true){ 57 for(i = 1; i <= n; i++){ 58 if(map[t][i] && !visit[i]){ 59 ans[ansi++] = i; 60 visit[i] = true; 61 t = i; 62 break; 63 } 64 } 65 if(i > n) break; 66 } 67 if(!map[s][t]){ 68 for(i = 1; i < ansi - 2; i++) 69 if(map[ans[i]][t] && map[s][ans[i + 1]])break; 70 w = ansi - 1; 71 i++; 72 t = ans[i]; 73 reverse(ans, i, w); 74 } 75 if(ansi == n) return; 76 for(j = 1; j <= n; j++){ 77 if(visit[j]) continue; 78 for(i = 1; i < ansi - 2; i++)if(map[ans[i]][j])break; 79 if(map[ans[i]][j]) break; 80 } 81 s = ans[i - 1]; 82 t = j; 83 reverse(ans, 0, i - 1); 84 reverse(ans, i, ansi - 1); 85 ans[ansi++] = j; 86 visit[j] = true; 87 } 88 } 89 90 int main(){ 91 //freopen("input.txt", "r", stdin); 92 int N, M; 93 while(~scanf("%d%d", &N, &M) && (N || M)){ 94 N *= 2; 95 bool map[maxN + 7][maxN + 7] = {0}; 96 int ans[maxN + 7] = {0}; 97 int ansi = 0; 98 for(int i = 0; i <= N; i++) 99 for(int j = 0; j <= N; j++) 100 i == j ? map[i][j] = map[j][i] = 0 : map[i][j] = map[j][i] = 1; 101 memset(ans, 0, sizeof(ans)); 102 for(int i = 1; i <= M; i++){ 103 int u, v; 104 scanf("%d%d", &u, &v); 105 map[u][v] = map[v][u]= 0; 106 } 107 Hamilton(ans, map, N); 108 for(int i = 0; i < N; i++) 109 printf(i == 0 ? "%d":" %d", ans[i]); 110 printf(" "); 111 112 } 113 return 0; 114 }