码迷,mamicode.com
首页 > 其他好文 > 详细

Little Sub and Traveling(杭师大第十二届校赛E题) 欧拉回路

时间:2019-03-20 01:01:16      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:span   color   不能   pen   http   close   传送门   ref   event   

题目传送门

题目大意:

  从0出发,每次只能跳到(i*2)%n或者(i*2+1)%n,求字典序最大的哈密顿回路。

思路:

  首先n为奇数时无解,先来证明这一点。

  先假设n为奇数,若要回到原点,则必定有一步是$a%n=0$,则$a=kn(k为整数)$。

  我们先假设a是通过$2x$的方式得到的,即$kn=2*x$,由于此时$n$为奇数,则k必定为偶数,由于$n>x$,所以$k<2$,k又不能等于0,所以此时k无解,a不是通过$s*x$的方法得到的

  那么$kn=2*x+1$,k为奇数,则$k=1  ,a=n=2*x+1$,也就是说,我们从x出发的这一步,是走到0的位置的,那么$2*x$这一步,就没有点是走到这里来的了,而$2*x=n-1$,又是我们必须到达的点,所以这种方法也无解。

  那么我们的假设错误,n必须是偶数。

  在偶数的情况下,我们发现$i$和$i+n/2$的出边相同。 我们把i和i+n/2看成一个点,现在就是一张n/2个点的图,所有点都有两条入边和两条出边,满足欧拉回路每个点度数都为偶数的性质! 于是只需要跑出欧拉回路就能对应到原问题了,介于欧拉回路算法的性质,贪心走较大的边即可保证字典序最大。(后面这一半是抄的官方题解)

  对于欧拉回路dfs过程,我们只要倒序输出,得到的就还是我们需要的字典序最大的回路。

技术图片
#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
typedef long long ll;
using namespace std;
const int maxn=20010;
int n,vis[maxn],q[maxn],cnt;
void dfs(int u){
    
    if(!vis[(u<<1|1)]){
        vis[(u<<1|1)]=1;
        dfs((u<<1|1)%(n>>1));
        q[++cnt]=(u<<1|1)%n;
    }
    if(!vis[(u<<1)]){
        vis[(u<<1)]=1;
        dfs((u<<1)%(n>>1));
        q[++cnt]=(u<<1)%n;
    }
}
int main(){
    while(cin>>n)
    {
        cnt=0;
        clr(vis,0);
        if(n%2==1){
            puts("-1");
            continue;
        }
        q[++cnt]=0;
        vis[0]=1;
        dfs(0);
        printf("0");
        while(cnt){
            printf(" %d",q[cnt--]);
        }
        puts("");
    }
    return 0;
}
View Code

 

Little Sub and Traveling(杭师大第十二届校赛E题) 欧拉回路

标签:span   color   不能   pen   http   close   传送门   ref   event   

原文地址:https://www.cnblogs.com/mountaink/p/10562430.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!