POJ 2438 哈密顿回路

Children‘s Dining

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 4730   Accepted: 754   Special Judge

Description

Usually children in kindergarten like to quarrel with each other. This situation annoys the child-care women. For instant, when diner time comes, a fierce conflict may break out when a certain couple of children sitting side by side who are hostile with each other. Although there aren‘t too many children dining at the same round table, but the relationship of "enemy" or "friend" may be very complex. The child-care women do come across a big problem. Now it is time for you to help them to figure out a proper arrangement of sitting, with which no two "enemy" children is adjacent.

Now we assume that there are 2 * n children who sit around a big table, and that none has more than n - 1 "enemies".

Input

The input is consisted of several test blocks. For each block, the first line contains two integers n and m (1 <= n <= 200, 0 <= m <= n (n - 1)). We use positive integers from 1 to 2 * n to label the children dining round table. Then m lines followed. Each contains positive integers i and j ( i is not equal to j, 1 <= i, j <= 2 * n), which indicate that child i and child j consider each other as "enemy". In a input block, a same relationship isn‘t given more than once, which means that if "i j" has been given, "j i" will not be given.

There will be a blank line between input blocks. And m = n = 0 indicates the end of input and this case shouldn‘t be processed.

Output

For each test block, if the proper arrangement exist, you should print a line with a proper one; otherwise, print a line with "No solution!".

Sample Input

1 0

2 2
1 2
3 4

3 6
1 2
1 3
2 4
3 5
4 6
5 6

4 12
1 2
1 3
1 4
2 5
2 6
3 7
3 8
4 8
4 7
5 6
5 7
6 8

0 0

Sample Output

1 2
4 2 3 1
1 6 3 2 5 4
1 6 7 2 3 4 5 8

解析 题目说保证 每个点的度数等于n所以 一定存在哈密顿回路 然后在他给出的图的补图上求一个哈密顿回路就可以了 套一个O(n*n)的板子。

哈密顿图:存在哈密顿回路的图

哈密顿图的判定:

一:Dirac定理(充分条件)

  设一个无向图中有N个顶点,若所有顶点的度数大于等于N/2,则哈密顿回路一定存在.(N/2指的是?N/2?,向上取整)

二:基本的必要条件

  设图G=<V, E>是哈密顿图,则对于v的任意一个非空子集S,若以|S|表示S中元素的数目,G-S表示G中删除了S中的点以及这些点所关联的边后得到的子图,则W(G-S)<=|S|成立.其中W(G-S)是G-S中联通分支数.

三:竞赛图(哈密顿通路)

  N(N>=2)阶竞赛图一点存在哈密顿通路.

AC代码

  1 #include <stdio.h>
  2 #include <string.h>
  3 using namespace std;
  4 const int maxn = 500+10;
  5 bool visit[maxn];
  6 int mapp[maxn][maxn],ans[maxn];
  7 int n,m;
  8 inline void _reverse(int s, int t) //将数组anv从下标s到t的部分的顺序反向
  9 {
 10     int temp;
 11     while(s  < t)
 12     {
 13         temp = ans[s];
 14         ans[s] = ans[t];
 15         ans[t] = temp;
 16         s++;
 17         t--;
 18     }
 19 }
 20 void Hamilton(int n)
 21 {
 22     memset(visit,false,sizeof(visit));
 23     int s = 1, t;//初始化取s为1号点
 24     int ansi = 2;
 25     int i, j;
 26     int w;
 27     int temp;
 28     for(i = 1; i <= n; i++) if(mapp[s][i]) break;
 29     t = i;//取任意邻接与s的点为t
 30     visit[s] = visit[t] = true;
 31     ans[0] = s;
 32     ans[1] = t;
 33     while(true)
 34     {
 35         while(true) //从t向外扩展
 36         {
 37             for(i = 1; i <= n; i++)
 38             {
 39                 if(mapp[t][i] && !visit[i])
 40                 {
 41                     ans[ansi++] = i;
 42                     visit[i] = true;
 43                     t = i;
 44                     break;
 45                 }
 46             }
 47             if(i > n) break;
 48         }
 49         w = ansi - 1;//将当前得到的序列倒置,s和t互换,从t继续扩展,相当于在原来的序列上从s向外扩展
 50         i = 0;
 51         _reverse(i, w);
 52         temp = s;
 53         s = t;
 54         t = temp;
 55         while(true) //从新的t继续向外扩展,相当于在原来的序列上从s向外扩展
 56         {
 57             for(i = 1; i <= n; i++)
 58             {
 59                 if(mapp[t][i] && !visit[i])
 60                 {
 61                     ans[ansi++] = i;
 62                     visit[i] = true;
 63                     t = i;
 64                     break;
 65                 }
 66             }
 67             if(i > n) break;
 68         }
 69         if(!mapp[s][t]) //如果s和t不相邻,进行调整
 70         {
 71             for(i = 1; i < ansi - 2; i++)//取序列中的一点i,使得ans[i]与t相连,并且ans[i+1]与s相连
 72                 if(mapp[ans[i]][t] && mapp[s][ans[i + 1]])break;
 73             w = ansi - 1;
 74             i++;
 75             t = ans[i];
 76             _reverse(i, w);//将从ans[i +1]到t部分的ans[]倒置
 77         }//此时s和t相连
 78         if(ansi == n) return;//如果当前序列包含n个元素,算法结束
 79         for(j = 1; j <= n; j++) //当前序列中元素的个数小于n,寻找点ans[i],使得ans[i]与ans[]外的一个点相连
 80         {
 81             if(visit[j]) continue;
 82             for(i = 1; i < ansi - 2; i++)if(mapp[ans[i]][j])break;
 83             if(mapp[ans[i]][j]) break;
 84         }
 85         s = ans[i - 1];
 86         t = j;//将新找到的点j赋给t
 87         _reverse(0, i - 1);//将ans[]中s到ans[i-1]的部分倒置
 88         _reverse(i, ansi - 1);//将ans[]中ans[i]到t的部分倒置
 89         ans[ansi++] = j;//将点j加入到ans[]尾部
 90         visit[j] = true;
 91     }
 92 }
 93 int main()
 94 {
 95     while(scanf("%d%d",&n,&m)!=EOF)
 96     {
 97         if(n==0)break;
 98         n*=2;
 99         memset(mapp,0,sizeof(mapp));
100         for(int i=1;i<=n;i++)
101             for(int j=1;j<=n;j++)
102                 mapp[i][j]=i==j?0:1;
103         for(int i=0;i<m;i++)
104         {
105             int u,v;
106             scanf("%d%d",&u,&v);
107             mapp[u][v]=mapp[v][u]=0;
108         }
109         Hamilton(n);
110         printf("%d",ans[0]);
111         for(int i=1;i<=n-1;i++)
112         {
113             printf(" %d",ans[i]);
114         }
115         printf("\n");
116     }
117 }

该算法的详细过程及哈密顿回路的其他知识

https://www.cnblogs.com/Ash-ly/p/5452580.html

原文地址:https://www.cnblogs.com/stranger-/p/9385306.html

时间: 2024-11-13 10:18:07

POJ 2438 哈密顿回路的相关文章

POJ 2438 Children&#39;s Dining(哈密顿回路)

题目链接:http://poj.org/problem?id=2438 题意: 有2*N个小朋友要坐在一张圆桌上吃饭,但是每两个小朋友之间存在一种关系,即敌人或者朋友,然后需要让你安排一个座位次序,使得相邻的两个小朋友都不会是敌人.假设每个人最多有N-1个敌人.如果没有输出"No solution!". 思路: 如果按照题意直接建图,每个点表示一个小朋友,小朋友之间的敌对关系表示两个点之间有边.问题是求小朋友围着桌子的座次就是求图中的一个环,但是要求这个环不能包含所给出的每条边,所有没

POJ 2438 解题报告

分析: 2*n个小朋友,每个最多有n-1个"敌人",显然是存在哈密顿回路的. 预处理边,然后找哈密顿回路. code #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; #define pb push_back #define sz(a) (int

poj 2438 Children&#39;s Dining

http://poj.org/problem?id=2438 题意: 有2*N个人要坐在一张圆桌上吃饭,有的人之间存在敌对关系,安排一个座位次序,使得敌对的人不相邻. 假设每个人最多有N-1个敌人.如果没有输出"No solution!". 如果i和j可以相邻,之间连一条边 每个人最多有N-1个敌人,所以每个人至少会连出去N+1条边 根据狄拉克定理,图一定是哈密顿图 所以本题不存在无解的情况 然后输出一条哈密顿回路就好了 有关哈密顿图与哈密顿回路的问题 参见文章 http://www.

Hamilton回路的判定与构造

定理1:在一个具有n个顶点的无向连通图G中,如果任意两个顶点的度数之和大于n,则G具有Hamilton回路.此条件为充分条件 定理2:设图G = <V,E>,是Hamilton图,则对于v的任意一个非空子集S,若以|S|表示S中元素数目,G-S表示G中删除了S中的点以及与这些点关联的边后得到的子图,则满足G-S的连通分支数W(G-S)<=|S|.此条件为必要条件. 构造Hamilton回路的算法过程,分成以下几个步骤: 1. 任意找两个相邻的节点 S 和 T,在它们基础上扩展出一条尽量长

POJ 2288 Islands And Bridges 状态压缩dp+哈密顿回路

题意:n个点 m条边的图,路径价值定义为相邻点乘积,若路路径c[i-1]c[i]c[i+1]中c[i-1]-c[i+1]有边 则价值加上三点乘积找到价值最大的哈密顿回路,和相应的方法数n<=13.暴力dfs O(13!) TLE 由于n<13 经典的状态压缩dp [状态] [当前点位置 ][前一点位置] 注意上一个状态必须合法才能进行转移设状态dp[s][i][j] 当前状态为s,当前点为i上一个点为j的最大价值, ans=max(dp[(1<<n)-1][i])dp[s][i][

POJ 3301 Texas Trip (三分)

题目链接 题意 : 给你若干个点,让你找最小的正方形覆盖这所有的点.输出面积. 思路 : 三分枚举正方形两对边的距离,然后求出最大,本题用的是旋转正方形,也可以用旋转点,即点的相对位置不变. 正方形从0度到180度变化的过程中,把所有点覆盖,面积肯定是有一个最小峰值,是一个凸函数.因此可以用三分法解决.这里有一个难点就是已知两个定点的x,y坐标,过这两个点做两条平行线,平行线并与x轴成d度的角,怎么算出两条平行线的距离. d1 = fabs(cos(d)*(yi-yj)-sin(d)*(xi-x

【POJ】【1739】Tony&#39;s Tour

插头DP 楼教主男人八题之一! 要求从左下角走到右下角的哈密顿路径数量. 啊嘞,我只会求哈密顿回路啊……这可怎么搞…… 容易想到:要是把起点和重点直接连上就变成一条回路了……那么我们就连一下~ 我们可以在整张图下面加两行:(例:3*5) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 红色的是原来的起点和终点,下面紫色的路径将这两个点连了起来= =然后这题瞬间就变回了Formula 1那题……求哈密顿回路数量,so easy有没有~(其实不这样

POJ - 3186 Treats for the Cows (区间DP)

题目链接:http://poj.org/problem?id=3186 题意:给定一组序列,取n次,每次可以取序列最前面的数或最后面的数,第n次出来就乘n,然后求和的最大值. 题解:用dp[i][j]表示i~j区间和的最大值,然后根据这个状态可以从删前和删后转移过来,推出状态转移方程: dp[i][j]=max(dp[i+1][j]+value[i]*k,dp[i][j-1]+value[j]*k) 1 #include <iostream> 2 #include <algorithm&

POJ 2533 - Longest Ordered Subsequence(最长上升子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2533 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK)