sgu122 分类: sgu 2015-02-...


构造题

改图满足Ore性质,是个很强的性质

1>先随机找到一条链。

2>如果这条链长度小于n,通过变换使其变成环(根据Ore性质可证明可行),
然后,选取不在环中的结点,找到相应位置,将环断开形成链,再将结点插入这条链,
不断重复这个过程直到链的长度等于n

3>通过变换使链变成环,输出路径


#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
#define MAXN 1005
#define SIZE 10005

int n;

bool mp[MAXN][MAXN]={false};

char ch[SIZE]={'\0'};
int cl;

bool hash[MAXN]={false};

int head,tail;int pre[MAXN]={false},sur[MAXN]={false};

int wl=0;


int numch(int l,int r)
{
    int i,ret=0;

    for(i=l;i<=r;i++)
    {
        ret*=10;
        ret+=ch[i]-'0';
    }

    return ret;
}

void dfs(int a)
{
    int i;

    hash[a]=true;wl++;tail=a;

    for(i=1;i<=n;i++)
      if(mp[a][i]==true && hash[i]==false)
         {sur[a]=i,pre[i]=a;dfs(i);return;}
}

void roll()
{
    int j,p,k,tmp;

    for(j=head;sur[j]!=false;j=sur[j])
        if(mp[j][tail]==true && mp[head][sur[j]]==true)
         {
            p=sur[j];

            sur[j]=tail;
            pre[head]=p;

//          tail~p
            for(k=tail;;k=sur[k])
            {
                tmp=pre[k];
                pre[k]=sur[k];
                sur[k]=tmp;

                if(k==p)break;
            }

            pre[tail]=j;
            sur[p]=head;

            return;
         }

}

void find()
{
    int i,j,k;

    for(i=1;i<=n;i++)
     if(hash[i]==false)
       for(j=1;j<=n;j++)
          if(mp[i][j]==true && hash[j]==true)
          {
             head=i;tail=pre[j];

             hash[i]=true;wl++;

             sur[pre[j]]=false;
             pre[j]=i;
             sur[i]=j;

             return;    
          }

}

int main()
{
    int i,j,q;

    #ifndef ONLINE_JUDGE
    freopen("sgu122.in","r",stdin);
    freopen("sgu122.out","w",stdout);
    #endif

    scanf("%d",&n);

    for(q=1;q<=n;q++)
    {
        while(scanf("%s",ch)!=EOF)
        {
            mp[q][numch(0,strlen(ch)-1)]=true;

            if(getchar()=='\n')break;
        }
    }


    head=1;
    dfs(1);

    while(wl<n)
    {
        roll();
        find();
    }

    roll();

    printf("1 ");   
    for(i=sur[1];i!=1;i=sur[i])
    {
        printf("%d ",i);
    }
    printf("1");

    #ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://www.cnblogs.com/dashgua/p/4723108.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值