POJ 2438 Children's Dining(哈密顿图)

来源:互联网 发布:linux常用指令 编辑:程序博客网 时间:2024/06/10 03:37

Description
给出一张有2*n个点的无向图和一些点的冲突关系,每个点最多与n-1个点冲突,求一条哈密顿回路
Input
多组用例,每组用例第一行为两个整数n和m,之后m行每行两个整数a和b表示a和b不能相邻,以n=m=0时结束输入1(1<=n<=200,0<=m<=n*(n-1)/2)
Output
如果存在哈密顿回路则输出之,否则输出”No solution!”
Sample Input
1 0

2 2
1 2
3 4

3 6
1 2
1 3
2 4
3 5
4 6
5 6

4 12
1 2
1 3
1 4
2 5
2 6
3 7
3 8
4 8
4 7
5 6
5 7
6 8

0 0
Sample Output
1 2
4 2 3 1
1 6 3 2 5 4
1 6 7 2 3 4 5 8
Solution
任意两点的度数和必然大于2*n,由哈密顿回路存在的充分条件知哈密顿回路必然存在,所以此题就是反向建图后求一条哈密顿回路
Code

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>using namespace std;#define maxn 444int n,m,ans[maxn],vis[maxn];bool M[maxn][maxn];void reverse(int l,int r){    while(l<r)    {        swap(ans[l],ans[r]);        l++,r--;    }}void Hamilton(){    int s=1,t,res=2,i,j;    memset(vis,0,sizeof(vis));    for(i=1;i<=n;i++)        if(M[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(M[t][i]&&!vis[i])                {                    ans[res++]=i,vis[i]=1,t=i;                    break;                }            if(i>n)break;        }        reverse(0,res-1);        swap(s,t);        while(1)        {            for(i=1;i<=n;i++)                if(M[t][i]&&!vis[i])                {                    ans[res++]=i,vis[i]=1,t=i;                    break;                }            if(i>n)break;        }        if(!M[s][t])        {            for(i=1;i<res-2;i++)                if(M[ans[i]][t]&&M[s][ans[i+1]])break;            t=ans[++i],reverse(i,res-1);        }        if(res==n)return ;        for(i=1;i<=n;i++)        {            if(vis[i])continue;            for(j=1;j<res-2;j++)if(M[ans[j]][i])break;            if(M[ans[j]][i])break;        }        s=ans[j-1],t=i;        reverse(0,j-1),reverse(j,res-1);        ans[res++]=i,vis[i]=1;    }}int main(){    while(~scanf("%d%d",&n,&m),n||m)    {        n*=2;        for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)                M[i][j]=i==j?0:1;        while(m--)        {            int u,v;            scanf("%d%d",&u,&v);            M[u][v]=M[v][u]=0;        }        Hamilton();        for(int i=0;i<n;i++)            printf("%d%c",ans[i],i==n-1?'\n':' ');    }}
0 0
原创粉丝点击