哈密頓迴路模板
阿新 • • 發佈:2018-12-19
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int maxn=405; int ans[maxn],g[maxn][maxn]; bool vis[maxn]; int n,m; void init() { memset(g,0,sizeof g); memset(vis,0,sizeof vis); } void revese(int ans[],int s,int t)//將ans陣列中s到t的部分倒置 { while(s<t){ swap(ans[s],ans[t]); s++; t--; } } void Hamilton() { int s=1,t;//初始化s取1號點 int ansi=2; int i,j,w; for(i=1;i<=n;i++) if(g[s][i]) break; t=i;//取任意連線s的點為t vis[s]=vis[i]=true; ans[0]=s;ans[1]=t; while(true){ while(true){//從t向外擴充套件 for(i=1;i<=n;i++) if(g[t][i]&&!vis[i]){ ans[ansi++]=i; vis[i]=true; t=i; break; } if(i>n)break; } //將當前得到的序列倒置,s和t互換,從t繼續擴充套件,相當於在原來的序列上從s擴充套件 w=ansi-1; i=0; revese(ans,i,w); swap(s,t); //從新的t向外擴充套件,相當於在原來的序列上從s向外擴充套件 while(true){ for(i=1;i<=n;i++) if(g[t][i]&&!vis[i]){ ans[ansi++]=i; vis[i]=true; t=i; break; } if(i>n)break; } //如果s和t不相鄰,進行調整 if(!g[s][t]){ for(i=1;i<ansi-2;i++) if(g[ans[i]][t]&&g[s][ans[i+1]])//取序列中一點i,使得ans[i]與t相連線且ans[i+1]與s相連 break; //將從ans[i+1]到t部分的ans[]倒置 w=ansi-1; i++; t=ans[i]; revese(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(g[ans[i]][j]) break; if(g[ans[i]][j]) break; } s=ans[i-1]; t=j; revese(ans,0,i-1);//將ans[]中s到ans[i-1]部分的ans[]倒置 revese(ans,i,ansi-1);//將ans[]中ans[i]到t的部分倒置 ans[ansi++]=j;//將點j加入到ans[]的尾部 vis[j]=true; } } int main() { while(scanf("%d%d",&n,&m)&&(n||m)) { n<<=1; init(); int a,b; while(m--){ scanf("%d%d",&a,&b); g[a][b]=g[b][a]=1; } Hamilton(); printf("%d",ans[0]); for(int i=1;i<n;i++) printf(" %d",ans[i]); printf("\n"); } return 0; }