哈密顿图

图G的一个回路,若他通过每个节点一次,就是哈密顿回路

有一个判定条件是设图G具有n个定点的无向联通图,如果图G任意两个定点度数之和大于n,则G具有哈密顿回路,满足这个条件则一定是哈密顿图,但是哈密顿图不一定满足这个条件,最简单的例子就是一个n阶圈图

目前判断哈密顿回路没有高效的算法,因此大多数情况会要求你输出这个哈密顿回路,可以通过这个判定条件进行构造

1.任意找俩个相邻的节点S,T通过这两个节点向两头扩展直到不能扩展为止,因此所有与节点S,T相邻的节点全部在这条链上

2.若S与T相邻则形成了回路,若不相邻则需要构造出一个回路,设这条链上有k+2个节点,因为k≤N-2,又因为d(S)+d(T)≥N,因此必定存在vi和vj与S,T都相邻,并且满足j=i+1,因此可以把路径变为S->vi->T->vj则形成了一个回路

3.因为已经构造出了一个没有重复节点的回路,因此现在需要判断这条环路上的节点个数是否为N,如果等于N则以找出了哈密顿回路,否则因为图是联通的必然在环上有点与环外点相邻,所以从这断开继续进行第二步

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
int ans[505],vis[505],G[505][505];
int n,m;
void revese(int *ans,int s,int t){
    while(s<t){
       swap(ans[s++],ans[t--]);
    }
    return;
}
void hamilton(){
    int i,j,w,s=1,t,tmp,ansi;
    s=1,ansi=2;
    for(i=1;i<=n;i++)
    if(G[s][i])
    break;
    t=i;
    vis[s]=vis[t]=1;
    ans[0]=s,ans[1]=t;
    while(1){
        while(1){
            for(i=1;i<=n;i++)
                if(G[t][i]&&!vis[i]){
                    ans[ansi++]=i;
                    vis[i]=1;
                    t=i;
                    break;
                }
            if(i>n)
            break;
        }
        revese(ans,0,ansi-1);
        swap(s,t);
        while(1){
            for(i=1;i<=n;i++)
            if(G[t][i]&&!vis[i]){
                ans[ansi++]=i;
                vis[i]=1;
                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]])
            break;
            i++;
            t=ans[i];
            revese(ans,i,ansi-1);
        }                                       //判断是否形成了回路
        if(ansi==n)
        return;
        for(j=1;j<=n;j++){
        if(vis[j])
        continue;
        for(i=1;i<ansi-2;i++)
        if(G[ans[i]][j])
        goto next;
        }                                       //没有的话则找哪个节点与外界相连
        next:
        s=ans[i-1];
        t=j;
        revese(ans,0,i-1);
        revese(ans,i,ansi-1);
        ans[ansi++]=j;
        vis[j]=1;
    }
}
int main(){
    int i,j,a,b;
    while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
        memset(vis,0,sizeof(vis));
        memset(ans,0,sizeof(ans));
        memset(G,0,sizeof(G));
        for(i=1;i<=m;i++){
            scanf("%d%d",&a,&b);
            G[a][b]=G[b][a]=1;                  //用邻接矩阵建图    
        }
        hamilton();
        for(i=0;i<n;i++)
        printf("%d ",ans[i]);
        printf("\n");
    }
    return 0;
}


 

你可能感兴趣的:(哈密顿图)