哈密顿图

来源:互联网 发布:mac电脑word加密 编辑:程序博客网 时间:2024/05/06 13:12

图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;}


 

0 0