#include <iostream>
#include <string.h>
#include <cstdio>
#include <cmath>
using namespace std;
const int N=410;
int mp[N][N];
int ans[N];
int vis[N];
int start;
int end;
int n,m;
int cnt;
void init()//预处理
{
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
if(i==j)
mp[i][j]=0;
else
mp[i][j]=1;
memset(vis,0,sizeof(vis));
memset(ans,0,sizeof(ans));
cnt=0;
}
void reverse(int s,int e)//将ans数组中s到t的部分倒置
{
while(s<e)
{
swap(ans[s],ans[e]);
s++;
e--;
}
}
void kuozhan()//从end点开始向外扩展
{
while(1)
{
int flag=0;
for(int i=1; i<=n; i++)
{
if(!vis[i]&&mp[end][i])
{
ans[cnt++]=i;
end=i;
vis[i]=1;
flag=1;
break;
}
}
if(!flag)//此时i=n+1,此时已经遍历全部的点
break;
}
}
void hamiltun()//汉密顿回路主体算法
{
start=1;
for(int i=1; i<=n; i++)//取任意邻接于s的点为end
if(mp[1][i])
{
end=i;
break;
}
vis[start]=1;
vis[end]=1;
ans[0]=start;
ans[1]=end;
cnt=2;
while(1)
{
kuozhan();//从end开始向外扩展
reverse(0,cnt-1);//将当前得到的序列倒置
swap(start,end);// start和end互换,
kuozhan();//从end继续扩展,相当于在原来的序列上从start向外扩展
//-------------------------------------------------------------------------------
//情况一:如果start和end不相邻,进行调整
int mid=0;
if(!mp[start][end])
{
for(int i=1; i<cnt-2; i++)//取序列中的一点i,使得ans[i]与end相连,ans[i+1]和start相连(一定有这种情况)
{
if(mp[ans[i]][end]&&mp[ans[i+1]][start])
{
mid=i+1;
break;
}
}
reverse(mid,cnt-1);//将ans[i+1]到end部分的ans[]倒置
end=ans[cnt-1];
}
//------------------------------------------------------------------------
//情况二:如果当前start和end相连
if(cnt==n)//如果当前序列中已经包含n个元素,算法结束
break;
for(int i=1; i<=n; i++)//如果当前序列中元素的个数小于n,寻找点ans[i],使得ans[i]与ans[]外的一点相连
{
if(!vis[i])
{
int j;
for(j=1; j<cnt-1; j++)
if(mp[ans[j]][i])
{
mid=j;
break;
}
if(mp[ans[mid]][i])
{
end=i;
mid=j;
break;
}
}
}
start=ans[mid-1];
reverse(0,mid-1);//将ans[]中s到ans[i-1] 部分的ans[]倒置
reverse(mid,cnt-1);//将ans[]中ans[i]到end的部分倒置
ans[cnt++]=end;//将新找到的这一点i,加入到ans[]尾部
vis[end]=1;//标记
//继续进行循环
//-------------------------------------------------------------------------------------
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(!n&&!m)
break;
n*=2;
int u,v;
init();
for(int i=1; i<=m; i++)
{
scanf("%d%d",&u,&v);//输出的两点是二者之间没有连通的路
mp[u][v]=mp[v][u]=0;
}
if(Is())
{hamiltun();
cout<<ans[0];
for(int i=1; i<cnt; i++)//输出哈密顿回路的访问路径
printf(" %d",ans[i]);
cout << endl;
}
else cout<<"不是汉米尔吨回路"<<endl;
}
return 0;
}
离散数学实验2
最新推荐文章于 2024-08-29 16:57:08 发布