poj2438

来源:互联网 发布:视频提取软件 编辑:程序博客网 时间:2024/06/02 03:34

在做这道题之前,我从来都不知道哈密顿图是什么东西,后来才知道,如果任意两个点的度之和大于等于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;}
0 0
原创粉丝点击