zoukankan      html  css  js  c++  java
  • Little Sub and Traveling(杭师大第十二届校赛E题) 欧拉回路

    题目传送门

    题目大意:

      从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
  • 相关阅读:
    官方文档翻译-Today
    RAC & MVVM 学习资料整理
    35种常用字体
    中文字体的种类
    自言自语(三)--部分中文字体
    自言自语(二)--英文无衬线体和有衬线体
    sketch字体设置技巧(一)---通过锚点改变字体形态
    提高设计档次的8个方法
    知识汇总09~bootstrap-select在Vue中的封装
    知识汇总08~字符串截取
  • 原文地址:https://www.cnblogs.com/mountaink/p/10562430.html
Copyright © 2011-2022 走看看