题目链接

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

分析:

本题给出的是小朋友之间的敌对关系,有敌对关系的不能挨着。所以建图的时候要初始化g[i][j]为1,如果相邻的话,就改为0,这样就建好图了。因为一共有2n个小朋友,但是每个人最多有n-1个敌人,所以每个小朋友可选择的人数肯定大于n+1,这就说明在建完图后,每个点的度数大于n+1,因此任意两个点的度数之和大于2n,满足哈密顿图的充分条件,所以一定存在哈密顿图。最后直接套上哈密顿图模板就能解出来了。

需要注意的一点就是m的值可能是为0 的,所有的小朋友彼此之家都没有敌对关系。

算法讲解

我们了解欧拉图谈论的实际上是图上关于边的可行遍性的问题,而哈密吨图的要求与点有关,图G的一个回路,若它通过图的每一个节点有且仅有一次,就是哈密顿回路。存在哈密顿回路的图就是哈密顿图。、

欧拉回路就是从图上的一点出发,经过所有的边必须且只能一次,最终回到原点的路径。

哈密顿回路就是从一点出发,经过所有的点必须且只能一次,最终回到起点的路径,图中有的边可以不经过,但是不会有边被经过两次。

满足哈密顿图的两个判定条件:

一:设图G是具有n个顶点的无向连通图,如果G中任意两个不同顶点的度数之和大于等于n,则G具有哈密顿回路,即G是哈密顿图。这是判断哈密顿图的充分条件,即不满足定理条件时也有可能存在哈密顿回路,图G也可能时哈密顿图,但是满足条件一定是哈密顿图。

二:如果图G<V,E>时哈密顿图,则对于V的任意一个非空子集,若以|S|表示S中元素的数目,G-S表示删除了S中的点以及这些所关联的边后得到的子图,则W(G-S)<=|S|成立。其中W(G-S)是G-S中联通分支数。这个判定方法上哈密顿图的必要条件,即如果不满足条件一丁不是哈密顿图,但满足条件还不能说这个图是哈密顿图。

构造哈密顿图的算法过程:

1.任意找两个相邻的节点S和T,在其基础上扩展出一条尽量长的没有重复节点的路径。也就是说,如果节点S与节点v相邻,而且节点v不在路径S-->T上,则可以把该路径变成v-->S-->T,然后把v变成新的S。从S和T分别向两头扩展,直到无法扩展为止,即所有与S或T相邻的节点都在S-->T上(这里的S和T是不断变化的)。

2.若S和T相邻,则路径S-->T形成一个回路。

3.若S和T不相邻,可以构造出一个回路。设路径S-->T上有k+2个节点,依次为S,v1,v2,···,vk和T。可以证明存在节点vi(i属于[1,k)),满足vi与T相邻,且v(i+1)与S相邻。找到上述节点vi,把原路径变成S-->vi-->T-->v(i+1),即形成一个回路。

4.现在有了一条没有重复节点的路径,如果其长度为n,则哈密顿回路就找到了。如果回路的长度小于n,由于整个图是连通的,所以在还回路上,一定存在一点与回路以外的点相邻。那么就把该回路从这一点处断开,就变成一条路径,同时还可以将与之相连的点加入路径。在按照步骤1的方法尽量扩展路径,则一定有新的节点被加进来。接着回到步骤2。

代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int n,m;
int tu[409][409];
int vis[409];
int ans[409];
void init()
{
for(int i=0; i<=n; i++)
for(int j=0; j<=n; j++)
{
if(i==j)
tu[i][j]=0;
else
tu[i][j]=1;
}
memset(vis,0,sizeof(vis));
memset(ans,0,sizeof(ans));
} void reverse(int ans[409],int s,int t)//反转函数,s和t分别表示反转开始和结束的界限
{
int temp;
while(s<t)
{
temp=ans[s];
ans[s]=ans[t];
ans[t]=temp;
s++;
t--;
}
}
void Hamilton()//哈密顿图模板
{
int s=1,t;//初始化取s为1号点
int ansi=2;
int i,j,w,temp;
for(i=1; i<=n; i++)
{
if(tu[s][i]==1)
break;//只要任意找到一个和起始点相邻的点就行
}
t=i;//这个点作为当前的结束点
vis[s]=vis[t]=1;
ans[0]=s;
ans[1]=t;//存储当前的起点和终点
while(true)
{
while(true)//从t点开始向外扩展
{
for(i=1; i<=n; i++)
{
if(tu[t][i]==1&&vis[i]==0)//找到任意的一个就可以向外扩
{
ans[ansi++]=i;
vis[i]=1;
t=i;//将t的值改变后接着往下找
break;
}
}
if(i>n) break;//相当于从t没法向外扩展了
}
//将新的到的序列倒置,s和t互换,这样接着从t开始向外扩展,相当于将原来的s向外扩展
w=ansi-1;
i=0;
reverse(ans,i,w);
//将s和t互换
temp=s;
s=t;
t=temp; //从新的t开始向外扩展,相当于原来的s向外扩展,代码与上面的原理一样
while(true)
{
for(i=1; i<=n; i++)
{
if(tu[t][i]==1&&vis[i]==0)
{
ans[ansi++]=i;
vis[i]=1;
t=i;
break;
}
}
if(i>n)break;
} //如果s和t不相邻的话,进行调整
if(tu[s][t]==0)
{
//取序列中的一点i,值得ans[i]与t相邻,ans[i+1]与s相邻
for(i=1; i<ansi-2; i++)
{
if(tu[ans[i]][t]==1&&tu[s][ans[i+1]]==1)
break;
}
//将从ans[i+1]到t的部分倒置
w=ansi-1;
i++;
t=ans[i];
reverse(ans,i,w);
}
//如果s和t相邻
if(ansi==n) return ;//当前序列中包含n个元素,算法结束
//当前序列元素个数小于n,寻找ans[i],使得ans[i]与ans外的一点相邻
for(j=1; j<=n; j++)
{
if(vis[j]) continue;
for(i=1; i<ansi-2; i++)
{
if(tu[ans[i]][j])
break;
}
if(tu[ans[i]][j])
break;
}
s=ans[i-1];
t=j;
//将ans中的s到ans[i-1]部分的ans倒置
reverse(ans,0,i-1);
//将ans中的ans[i+1]到t部分的ans倒置
reverse(ans,i,ansi-1);
//将j加入到尾部
ans[ansi++]=j;
vis[j]=1; }
}
int main()
{
int u,v;
while(~scanf("%d%d",&n,&m),n|m)
{
n=n*2;
init();
for(int i=0; i<m; i++)
{
scanf("%d%d",&u,&v);
tu[u][v]=tu[v][u]=0;//建立反图,表示这两个小朋友不能坐在一起,用图理解的话就是这两个点不相邻
}
Hamilton();
printf("%d",ans[0]);
for(int i=1; i<n; i++)
printf(" %d",ans[i]);
printf("\n");
}
return 0;
}

POJ 2438 Children’s Dining (哈密顿图模板题之巧妙建反图 )的更多相关文章

  1. poj 2438 Children's Dining

    http://poj.org/problem?id=2438 题意: 有2*N个人要坐在一张圆桌上吃饭,有的人之间存在敌对关系,安排一个座位次序,使得敌对的人不相邻. 假设每个人最多有N-1个敌人.如 ...

  2. POJ 2438 Children's Dining(哈密顿回路)

    题目链接:http://poj.org/problem?id=2438 本文链接:http://www.cnblogs.com/Ash-ly/p/5452615.html 题意: 有2*N个小朋友要坐 ...

  3. POJ 1273 - Drainage Ditches - [最大流模板题] - [EK算法模板][Dinic算法模板 - 邻接表型]

    题目链接:http://poj.org/problem?id=1273 Time Limit: 1000MS Memory Limit: 10000K Description Every time i ...

  4. POJ 1860 Currency Exchange【bellman-Ford模板题】

    传送门:http://poj.org/problem?id=1860 题意:给出每两种货币之间交换的手续费和汇率,求出从当前货币s开始交换回到s,能否使本金增多. 思路:bellman-Ford模板题 ...

  5. POJ 1258 Agri-Net 【Prime】模板题

    题目链接>>> 题目大意:     给你N*N矩阵,表示N个村庄之间的距离.FJ要把N个村庄全都连接起来,求连接的最短距离(即求最小生成树).解析如下: #include <c ...

  6. POJ 3624 Charm Bracelet(01背包模板题)

    题目链接 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 52318   Accepted: 21912 Descriptio ...

  7. POJ 1273:Drainage Ditches 网络流模板题

    Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 63339   Accepted: 2443 ...

  8. POJ 2186:Popular Cows Tarjan模板题

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 25945   Accepted: 10612 De ...

  9. POJ 1258:Agri-Net Prim最小生成树模板题

    Agri-Net Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 45050   Accepted: 18479 Descri ...

随机推荐

  1. ACM数论之旅11---浅谈指数与对数(长篇)(今天休息,不学太难的数论> 3<)

    c/c++语言中,关于指数,对数的函数我也就知道那么多 exp(),pow(),sqrt(),log(),log10(), exp(x)就是计算e的x次方,sqrt(x)就是对x开根号 pow()函数 ...

  2. 计算机网络【6】—— 从浏览器输入URL到显示页面发生了什么

    当在浏览器地址栏输入网址,如:www.baidu.com后浏览器是怎么把最终的页面呈现出来的呢?这个过程可以大致分为两个部分:网络通信和页面渲染. 一.网络通信 互联网内各网络设备间的通信都遵循TCP ...

  3. linux下tomcat、jenkins环境搭建

    1.安装JDK  我不列出来了,自行百度 java -version 2.安装tomcat (1)将下载的tomcat压缩包 tar -zxvf apache-tomcat-8.5.29.tar.gz ...

  4. innobackupx备份原理

    1.工具内容 该软件安装完成会有四个工具,如下所示: usr├── bin│ ├── innobackupex│ ├── xbcrypt│ ├── xbstream│ └── xtrabackup 其 ...

  5. MT【119】关于恒成立的一道压轴题

    分析:处理恒成立问题,一般先代特殊值缩小范围.令x=0,则f(a)<f(0),容易知a<0. 排除答案C.容易理解a趋向于0时候,是可以的,排除D.在剩余的A,B选项里,显然偏向于A.因为 ...

  6. JDK中的SimpleDateFormat线程非安全

    在JDK中使用SimpleDateFormat的时候都会遇到线程安全的问题,在JDK文档中也说明了该类是线程非安全的,建议对于每个线程都创建一个SimpleDateFormat对象.如下面一个Case ...

  7. 【HDU4336】Card Collector(Min-Max容斥)

    [HDU4336]Card Collector(Min-Max容斥) 题面 Vjudge 题解 原来似乎写过一种状压的做法,然后空间复杂度很不优秀. 今天来补一种神奇的方法. 给定集合\(S\),设\ ...

  8. 【UOJ#80】二分图最大权匹配(KM)

    题面 UOJ 题解 模板qaq #include<iostream> #include<cstdio> #include<cstdlib> #include< ...

  9. 【BZOJ2731】三角形覆盖问题

    想象一条平行于\(y\)轴的扫描线,从低往高扫描.如何确定关键高度才能使每两个关键高度之间分割出的图形易于计算呢? 关键高度有:三角形底边高度.三角形上顶点高度.三角形交点的高度. ​ 如此分割,我们 ...

  10. BZOJ4036 [HAOI2015]按位或 【minmax容斥 + 期望 + FWT】

    题目链接 BZOJ4036 题解 好套路的题啊,,, 我们要求的,实际上是一个集合\(n\)个\(1\)中最晚出现的\(1\)的期望时间 显然\(minmax\)容斥 \[E(max\{S\}) = ...