SGU122 满足ORE性质的图求哈密尔顿路径

ORE性质,任意两个互异不相邻的点的度的和大于等于n(去除重边和自环),即deg(u)+deg(v)>=n。

详细资料:http://www.nocow.cn/index.php/Sgu/122http://blog.csdn.net/volzkzg/article/details/7514103

解决方法就是: 从一点开始向两边扩展,直至不能扩展,然后连成环,判断点数是否为n,若不为n,则在环外任意找与该环相连的一点进行增广,然后重复扩展连环过程。

PS:SGU卡常数,卡输入绝了... = =|||,把递归子程序换成循环,输入换成getchar输入才过... 其实主要原因还是在输入上,试了三种输入方法,时间分别173ms,343ms,562ms(也就是超时,= =|||)

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
bool adj[1105][1105],visited[1105];
int l[1105],r[1105],listnum,head,tail,n;
//void FindHead()
//{
//    int i;
//    bool flag=true;
//    while(flag)
//    {
//        flag=false;
//        for(i=1;i<=n;++i)
//        {
//            if(!visited[i]&&adj[head][i])
//            {
//                l[head]=i;
//                r[i]=head;l[i]=0;
//                visited[i]=true;
//                listnum++;
//                head=i;
//                flag=true;
//            }
//        }
//    }
//}
//void FindTail()
//{
//    int i;
//    bool flag=true;
//    while(flag)
//    {
//        flag=false;
//        for(i=1;i<=n;++i)
//        {
//            if(!visited[i]&&adj[tail][i])
//            {
//                r[tail]=i;
//                l[i]=tail;r[i]=0;
//                visited[i]=true;
//                listnum++;
//                tail=i;
//                flag=true;
//            }
//        }
//    }
//}
//void Reverse()
//{
//    if(adj[head][tail])
//    {
//        l[head]=tail;
//        r[tail]=head;
//        return ;
//    }
//    int i,j;
//    for(i=r[head];r[i]!=tail;i=r[i])
//    {
//        if(adj[head][r[i]]&&adj[tail][i])
//        {
//            l[head]=r[head];r[head]=r[i];
//            l[r[i]]=head;
//            r[tail]=i;
//            r[i]=l[i];l[i]=tail;
//            tail=l[head];
//            for(j=r[i];j!=head;j=r[j])
//            {
//                swap(l[j],r[j]);
//            }
//            return ;
//        }
//    }
//}
//void Add()
//{
//    int i,j,num=0,p=head,pos;
//    for(i=1;i<=n;++i)
//    {
//        if(!visited[i])
//        {
//            pos=i;
//            visited[i]=true;
//            break;
//        }
//    }
//    for(i=head;;i=r[i])
//    {
//        if(adj[i][pos])
//        {
//            l[r[i]]=0;
//            head=r[i];
//            r[i]=pos;
//            l[pos]=i;r[pos]=0;
//            tail=pos;
//            listnum++;
//            return ;
//        }
//    }
//}
//void Print()
//{
//    int i;
//    for(i=1;r[i]!=1;i=r[i])
//    {
//        printf("%d ",i);
//    }
//    printf("%d 1\n",i);
//}
//void Work()
//{
//    while(1)
//    {
//        FindHead();
//        FindTail();
//        if(listnum==n)
//        {
//            Reverse();
//            Print();
//            return ;
//        }
//        Reverse();
//        Add();
//    }
//}
void Work()
{
    int i,j,k,pos;
    bool flag;
    while(1)
    {
        flag=true;
        while(flag)
        {
            flag=false;
            for(i=1;i<=n;++i)
            {
                if(!visited[i]&&adj[head][i])
                {
                    l[head]=i;
                    r[i]=head;l[i]=0;
                    visited[i]=true;
                    listnum++;
                    head=i;
                    flag=true;
                }
            }
        }
        flag=true;
        while(flag)
        {
            flag=false;
            for(i=1;i<=n;++i)
            {
                if(!visited[i]&&adj[tail][i])
                {
                    r[tail]=i;
                    l[i]=tail;r[i]=0;
                    visited[i]=true;
                    listnum++;
                    tail=i;
                    flag=true;
                }
            }
        }
        if(adj[head][tail])
        {
            l[head]=tail;
            r[tail]=head;
        }
        else
        {
            for(i=r[head];r[i]!=tail;i=r[i])
            {
                if(adj[head][r[i]]&&adj[tail][i])
                {
                    l[head]=r[head];r[head]=r[i];
                    l[r[i]]=head;
                    r[tail]=i;
                    r[i]=l[i];l[i]=tail;
                    tail=l[head];
                    for(j=r[i];j!=head;j=r[j])
                    {
                        swap(l[j],r[j]);
                    }
                    break;
                }
            }
        }
        if(listnum==n)
        {
            for(i=1;r[i]!=1;i=r[i])
            {
                printf("%d ",i);
            }
            printf("%d 1\n",i);
            return ;
        }
        else
        {
            for(i=1;i<=n;++i)
            {
                if(!visited[i])
                {
                    pos=i;
                    visited[i]=true;
                    break;
                }
            }
            for(i=head;;i=r[i])
            {
                if(adj[i][pos])
                {
                    l[r[i]]=0;
                    head=r[i];
                    r[i]=pos;
                    l[pos]=i;r[pos]=0;
                    tail=pos;
                    listnum++;
                    break;
                }
            }
        }
    }
}
void Init()
{
    memset(adj,false,sizeof(adj));
    memset(visited,false,sizeof(visited));
    char ch;
    scanf("%d",&n);
    int i,j;
    for(i=1;i<=n;++i)
    {
        scanf("%d",&j);
        adj[i][j]=adj[j][i]=true;
        ch=getchar();
        while(ch!='\n'&&ch!=EOF)
        {
            scanf("%d",&j);
            adj[i][j]=adj[j][i]=true;
            ch=getchar();
        }
    }
    listnum=head=tail=1;
    visited[1]=true;
}
int main()
{
    Init();
    Work();
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值