zoukankan      html  css  js  c++  java
  • POJ1392 Ouroboros Snake 欧拉回路

    题意:对于一个长度为2^N的循环序列,从某一个位置开始依次取N个,这样就能够生成2^N个序列,现在要求输出一个最小的满足要求的循环序列。输出这个序列生成的第K个数字是多少?

    解法:套用Fleury算法,构边的时候保持从小到大的顺序即可。如果是生成N为序列的话,就考虑前N-1位构成的节点相互的连的边(例如三位数就可以这样构边 00 --> 01 --> 11那么这两条边就代表生成了001和011这两个数字),输出欧拉回路即可。

    代码如下:

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = (1 << 15);
    int n, k;
    int stk[MAXN+5];
    int path[MAXN+5];
    int ans[MAXN+5];
    int top;
    
    struct Node { // f用来标志边是否被删除 
        int v, f;
        int next;
    }e[MAXN*2+5]; // 每个节点最多生成两条边
    
    int head[MAXN+5], idx; 
    
    void insert(int a, int b) {
    //    printf("a = %d, b = %d\n", a, b);
        e[idx].v = b, e[idx].f = 1;
        e[idx].next = head[a];
        head[a] = idx++;
    }
    
    void dfs(int x) {
        for (int i = head[x]; i != -1; i = e[i].next) {
            if (e[i].f) {
                stk[top++] = e[i].v;
                e[i].f = 0;
                dfs(e[i].v);
                break;
            }
        }    
    }
    
    void fleury(int ss) {
        int cnt = 0;
        top = 0;
        stk[top++] = ss;
        while (top > 0) {
            int brige = 1, v = stk[top-1];
            for (int i = head[v]; i != -1; i = e[i].next) {
                if (e[i].f) {
                    brige = 0;
                    break;
                }
            }
            if (!brige) {
                dfs(v);
            } else {
                --top; // 某联通子集中节点出栈
                path[cnt++] = v;
            }
        }
        for (int i = cnt-2, j = 0; i >= 0; --i, ++j) {
            ans[j] = (path[i+1] << 1) | (path[i] & 1);
        //    printf("path[%d] = %d\n", j, ans[j]);
        }
    }
    
    int main() {
        while (scanf("%d %d", &n, &k), n|k) {
            idx = 0; 
            memset(head, 0xff, sizeof (head));
            int lim = 1 << (n-1); // 只将前n-1位作为节点,后面一位放到边上,那么每条边都遍历一遍即使最后的结果 
        //    printf("lim = %d\n", lim);
            for (int i = 0; i < lim; ++i) {
                // 从每个节点有两个节点出去
                int t = i & ((lim-1)>>1);
                insert(i, t<<1|1);
                insert(i, t<<1); // 由于采用的前插入,因此较小的边后插入 
            }
            fleury(0);
            printf("%d\n", ans[k]);
        }
        return 0;
    }
  • 相关阅读:
    React元素渲染
    初识JSX
    微信小程序复制文本到剪切板
    微信小程序报错request:fail url not in domain list
    小程序,通过自定义编译条件,模拟推荐人功能
    积分抵扣逻辑
    微信小程序 switch 样式
    tomcat 配置开启 APR 模式
    tomcat8 传输json 报错 Invalid character found in the request target. The valid characters are defined in RFC 3986
    c++数组初始化误区
  • 原文地址:https://www.cnblogs.com/Lyush/p/3038508.html
Copyright © 2011-2022 走看看