1 /* 2 POJ - 2438 哈密顿回路 3 图的可行遍问题:一般就是哈密顿图和欧拉图 4 这类问题,代码和算法本身简单,关键就在于建模。 5 一般判断问题只要判断是否可行遍历! 6 但是有的时候会有奇葩的要求: 7 例如:遍历一张欧拉回路图:深度遍历不回溯法,o(n) 8 遍历哈密顿回路:这道题 9 言归正传: 10 1、哈密顿图定义:从一个点出发、经过所有的点必须且只能一次,最终回到起点。图中有边可以不经过,但是不能经过两次。 11 2、存在的充分条件:图有n个顶点,如果图中任意两个不同的顶点的度数之和大于等于n,则图是哈密顿图。 12 3、遍历哈密顿图的算法:如下 13 14 解题思路: 15 1、题目是说,小朋友围一圈坐着,仇恨的不能坐在一起,让你安排座位。 16 2、建图:可以连着坐的点连一条线,这道题就是求一个哈密顿的可行遍历。 17 3、判断是否有解:因为每个人最多有n-1个敌人,然而有2*n个小朋友,满足上述充分条件,必然有解。 18 19 */ 20 #include <iostream> 21 #include <string.h> 22 #include <stdio.h> 23 #include <cmath> 24 #include <vector> 25 #define LL long long 26 #define maxn 410 27 using namespace std; 28 29 bool map[maxn][maxn]; 30 int ans[maxn]; 31 inline void reverse(int s,int t){ 32 while(s<t){ 33 swap(ans[s],ans[t]); 34 s++;t--; 35 } 36 } 37 void Hamilton(int n){ 38 int s=1,t; 39 int ansi=2; 40 int w,i,j; 41 bool visit[maxn]={false}; 42 for(i=1;i<=n;i++){ 43 if (map[s][i]) break; 44 } 45 t=i; 46 visit[s]=visit[t]=true; 47 ans[0]=s; 48 ans[1]=t; 49 while(1){ 50 while(1){ 51 for(i=1;i<=n;i++){ 52 if (map[t][i] && !visit[i]){ 53 ans[ansi++]=i; 54 visit[i]=true; 55 t=i; 56 break; 57 } 58 } 59 if (i>n) break; 60 } 61 w=ansi-1; 62 i=0;reverse(i,w); 63 swap(s,t); 64 while(1){ 65 for(i=1;i<=n;i++){ 66 if (map[t][i] && !visit[i]){ 67 ans[ansi++]=i; 68 visit[i]=true; 69 t=i; 70 break; 71 } 72 } 73 if (i>n) break; 74 } 75 if (!map[s][t]){ 76 for(i=1;i<ansi-2;i++) if (map[ans[i]][t] && map[s][ans[i+1]]) break; 77 w=ansi-1; 78 i++; 79 t=ans[i]; 80 reverse(i,w); 81 } 82 if (ansi==n) return ; 83 for(j=1;j<=n;j++){ 84 if (visit[j]) continue; 85 for(i=1;i<ansi-2;i++) if (map[ans[i]][j]) break; 86 if (map[ans[i]][j]) break; 87 } 88 s=ans[i-1]; 89 t=j; 90 reverse(0,i-1); 91 reverse(i,ansi-1); 92 ans[ansi++]=j; 93 visit[j]=true; 94 } 95 } 96 int n,m; 97 int main(){ 98 while(cin>>n>>m){ 99 if (n==0 && m==0) break; 100 memset(map,0,sizeof(map)); 101 for(int i=1;i<=m;i++){ 102 int u,v; 103 scanf("%d%d",&u,&v); 104 map[u][v]=map[v][u]=true; 105 } 106 for(int i=1;i<=2*n;i++){ 107 for(int j=1;j<=2*n;j++) 108 if (i==j) continue; 109 else map[i][j]=!map[i][j]; 110 } 111 Hamilton(2*n); 112 for(int i=0;i<2*n;i++) 113 if (i!=2*n-1) printf("%d ",ans[i]);else printf("%d\n",ans[i]); 114 } 115 return 0; 116 }
POJ - 2438 哈密顿回路遍历,布布扣,bubuko.com
原文:http://www.cnblogs.com/little-w/p/3614994.html