Children's Dining(POJ 2438)

Topic Link

Title 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 Format

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 Format

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

The meaning of problems

There are 2 * N subject to the effect a child sitting on a round table to eat, adjacent to the requirements of the two children are not enemies, and each person has at most N-1 enemy, seeking to meet a series of requirements.

analysis

Typical Hamilton loop template title. Each of the questions in a maximum of N-1 enemy understood each vertex of at least N + 1, does not meet any two adjacent vertices u, v, has a degree [u] + degree [v ] ≥ N, there must Hamilton loop in this problem.
FIG given subject according to established anti FIG G G ', the anti-spreading sequence according to FIG Dirac theorem, seeking to satisfy the meaning of the title Hamilton circuit.

Theorem configuration Dirac Hamiltonian circuit undirected graph

  • To find any two adjacent nodes S and T, on the basis of which extend in a path as long as possible without repeating node, i.e. if the node v S and adjacent, but not on the path S v - a> T, then this path can become v -> S -> T, then v becomes the new S. Extended from the two S and T, respectively, can not expand until the date, S or T i.e. all adjacent nodes in the path S -> T on
  • If the adjacent S T, the path S -> T forms a loop
  • If T and S are not adjacent, may be constructed out of a loop. - route S -> T k + 2 has the nodes, followed by S, v1, v2, ..., vk, T. Can prove the existence of the node vi (I belong to [1, k]), and T adjacent to satisfy vi and vi + 1 adjacent to S, find the node vi, the original paths into S -> vi -> T -> vi + 1 -> S, i.e. the formation of a loop.
  • So far, the circuit has been constructed without a repeating node, if its length is N, then the loop to find the Hamiltonian. If the length of the loop is less than N, since the entire graph is connected, so in the loop, adjacent to the point that there must be outside the loop. Then the loop is disconnected from at this point, changed back to a path, and can also be added to the adjacent point of the path. The method of step 1 further propagation paths as much as possible, it must have a new node is added in, then back to the path 2

Source

//#include <bits/stdc++.h>	//poj中不能使用万能头
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#define MAXN 405
using namespace std;
int m,n,path[MAXN];
bool g[MAXN][MAXN],used[MAXN];
void Reverse(int a[],int s,int t)
{
	int tmp;
	while(s<t){
		/*tmp=a[s];
		a[s]=t;
		a[t]=s;*/
		swap(a[s],a[t]);
		s++;
		t--;
	}
}
void Hamilton()
{
	int s=1,t;	//初始化s,t 
	for(int i=1;i<=n;i++)
		if(g[s][i]){
			t=i;
			break;
		}
	used[s]=used[t]=true;
	path[0]=s,path[1]=t;
	int cnt=2;
	while(1){
		while(1){	//t向外扩展 
			bool flag=true;
			for(int i=1;i<=n;i++){
				if(g[t][i]&&!used[i]){
					path[cnt++]=i;
					used[i]=true;
					t=i;
					flag=false;
					break; 
				}
			}
			if(flag)break;
		}
		Reverse(path,0,cnt-1);	//翻转数组 
		swap(s,t);	//交换s,t
		while(1){	//t向外扩展 
			bool flag=true;
			for(int i=1;i<=n;i++){
				if(g[t][i]&&!used[i]){
					path[cnt++]=i;
					used[i]=true;
					t=i;
					flag=false;
					break; 
				}
			}
			if(flag)break;
		} 
		if(!g[s][t]){	//s与t不相邻 
			int i;		//取path[i]中与t相邻且,path[i+1]与s相邻 
			for(i=1;i<cnt-2;i++)
				if(g[path[i]][t]&&g[s][path[i+1]]) 
					break;
			i++;
			t=path[i];
			Reverse(path,i,cnt-1);	//将path[i+1]到t部分倒置 
		}	//此时s和t相连
		if(cnt==n)	return ;	//当前序列包含n个元素,算法结束 
		else{	//当前序列元素小于n,寻找path[i],使得path[i]与path[]外一点相连 
			int i,j;
			for(j=1;j<=n;j++){
				if(used[j])continue;
				for(i=1;i<cnt-2;i++)
					if(g[path[i]][j])
						break;
				if(g[path[i]][j])break;
			}
			s=path[i-1],t=j;
			Reverse(path,0,i-1);
			Reverse(path,i,cnt-1);
			path[cnt++]=j;
			used[j]=true; 
		} 
	}
}
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
		memset(g,true,sizeof(g));	//初始化 
		memset(used,false,sizeof(used));
		memset(path,0,sizeof(path));
		n*=2;
		for(int i=0;i<=n;i++)g[i][i]=false;
		for(int i=1;i<=m;i++){
			int x,y;
			scanf("%d%d",&x,&y);
			g[x][y]=g[y][x]=false;
		}
		Hamilton();
		for(int i=0;i<n;i++)printf("%d ",path[i]);
		printf("\n");
	}
}
 
Published 19 original articles · won praise 0 · Views 134

Guess you like

Origin blog.csdn.net/weixin_43960284/article/details/105237174