在做这道题之前,我从来都不知道哈密顿图是什么东西,后来才知道,如果任意两个点的度之和大于等于n,则一定为哈密顿图
题意是,有2n个孩子,每个孩子最多有n-1个敌对,说明除了自己以外,一定有至少n个人与他相连,所以任意两个人的度数一定大于等于n,所以是哈密顿图
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
const int maxn=420;
int n,m;
bool mp[maxn][maxn];
int s,T,cnt,ans[maxn];
bool vis[maxn];
void reverse(int l,int r)
{
while(l<r)
{
swap(ans[l],ans[r]);
l++;
r--;
}
}
void expend()
{
while(1)
{
bool flag=0;
for(int i=1; i<=n; i++)
{
if(!vis[i]&&mp[T][i])
{
ans[cnt++]=i;
T=i;
vis[i]=1;
flag=1;
break;
}
}
if(!flag)
break;
}
}
void ham()
{
memset(vis,0,sizeof(vis));
s=1;
for(T=2; T<=n; T++)
{
if(mp[s][T])
break;
}
cnt=2;
ans[0]=s;
ans[1]=T;
vis[s]=1;
vis[T]=1;
while(1)
{
expend();
reverse(0,cnt-1);
swap(s,T);
expend();
int mid=0;
if(!mp[s][T])
{
for(int i=1; i<cnt-2; i++)
{ // 设路径S到T上有k+2个节点,依次为S,v1,v2…… vk和T. 除了s,t以外,一共还有2n-2个节点,因为每个至少连n个节点,所以他俩一共至少连2n个节点,所以一定存在满足vi与T相邻,且vi+1与S相邻
if(mp[ans[i]][T]&&mp[ans[i+1]][s])
{
mid=i+1;
break;
}
}
reverse(mid,cnt-1);
//把原路径变成S→vi→T→vi+1→S,即形成了一个回路
T=ans[cnt-1];
}
if(cnt==n)
break;
//现在我们有了一个没有重复节点的回路.如果它的长度为N,则汉密尔顿回路就找到了
//否则,由于整个图是连通的,所以在该回路上,一定存在一点与回路以外的点相邻
//那么从该点处把回路断开,就变回了一条路径,再按照步骤1的方法尽量扩展路径
for(int i=1; i<=n; i++)
{
if(!vis[i])
{
int j;
for(j=1; j<cnt-1; j++)
{
if(mp[ans[j]][i])
break;
}
if(mp[ans[j]][i])
{
T=i;
mid=j;
break;
}
}
}
s=ans[mid-1];
reverse(0,mid-1);
reverse(mid,cnt-1);
ans[cnt++]=T;
vis[T]=1;
}
}
int main()
{
int u,v;
while(cin>>n>>m)
{
if(n==0&&m==0)
break;
n*=2;
memset(mp,1,sizeof(mp));
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
if(i==j)
mp[i][j]=0;
}
for(int i=1; i<=m; i++)
{
cin>>u>>v;
mp[u][v]=0;
mp[v][u]=0;
}
ham();
cout<<ans[0];
for(int i=1;i<cnt;i++)
cout<<" "<<ans[i];
cout<<endl;
}
return 0;
}