POJ - 2438 哈密顿回路遍历

  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 }

 

posted @ 2014-03-21 00:36  little_w  阅读(966)  评论(0编辑  收藏  举报