UESTC 1642 老当益壮, 宁移白首之心? 欧拉回路、Fleury算法

来源:互联网 发布:爱情观知乎 编辑:程序博客网 时间:2024/06/05 14:26

老当益壮, 宁移白首之心?

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)


Submit  Status
请构造一个01串,使其满足以下条件:


环状(即首尾相连)
每一位取值为0或1
长度是2^n
对于每个(2^n个)位置,从其开始沿逆时针方向的连续的n位01串(包括自己)构成的数均不相同,即0到(2^n)−1中的数各出现一次


Input

输入一个整数n(1≤n≤15)


Output

输出任一一个长度为2n且满足题意的01串(顺逆时针均可),保证输入有解。


Sample input and output

Sample Input Sample Output

3                             00010111


Hint

样例的00010111,对于每个位置,沿逆时针方向连续长度为3的01串有:000,001,010,101,011,111,110,100即为0−7的所有数字


Source

2017 UESTC Training for Graph Theory

UESTC 1642 老当益壮, 宁移白首之心?


My Solution

题意:构造一个01串,使其满足以下条件:
环状(即首尾相连)
每一位取值为0或1
长度是2^n
对于每个(2^n个)位置,从其开始沿逆时针方向的连续的n位01串(包括自己)构成的数均不相同,
即0到(2^n) - 1中的数各出现一次


欧拉回路、Fleury算法
考虑用一条边表示一个数,那么题目要求就是无重复的遍历完所有边,
则这是一个欧拉图的问题。
对于有公共点的两条边,第一个的后n-1位和第二个的前n-1相同。
这样将一条边的前n-1位和后n-1位作为点,连边,这样来表示它。
如:对于01101,我们可以从0110向1101建一条有向边表示01101.
于是所建图有2^(n-1)个点,和2^n条边。
对于任一两个点,如果它们的前n-2位和后n-2位相同,就连一条有向边,
这样所得到的图一定是欧拉图,
因为每个点的入度和出度都是2,一定存在欧拉回路。
时间复杂度 O(V + E)
空间复杂度 O(V + E)


#include <iostream>#include <cstdio>#include <cstring>#include <vector>using namespace std;typedef long long LL;typedef pair<int, int> ii;const int MAXN = (1<<14) + 8;const int MAXM = (1<<15) + 8;vector<ii> adj[MAXN];bool vis[MAXM];inline void add(int x, int y, int z){ //z is the edge who disjoint x and y.    adj[x].push_back(ii(z, y));}vector<int> path;inline void dfs(int u){    int v, e;    while(!adj[u].empty()){        v = adj[u].back().second, e = adj[u].back().first;        adj[u].pop_back();        if(!vis[e]){            vis[e] = true;            dfs(v);            path.push_back(e);        }    }}inline bool get_path(){    int i, j, sz;    int origin = 0;    path.clear();    memset(vis, false, sizeof vis);    dfs(origin);    return true;}int main(){    #ifdef LOCAL    freopen("i.txt", "r", stdin);    //freopen("i.out", "w", stdout);    int T = 1;    while(T--){    #endif // LOCAL    //ios::sync_with_stdio(false); cin.tie(0);    int n, u, v, i;    //cin >> n;    scanf("%d", &n);    for(i = 0; i < (1<<n); i++){        u = i >> 1;        v = i % (1<<n-1);        add(u, v, i);    }    get_path();    int sz = 1<<n;    for(i = 0; i < sz; i++){        putchar(char('0' + (path[i] & 1)));    }    putchar('\n');    #ifdef LOCAL    cout << endl;    }    #endif // LOCAL    return 0;}


  Thank you!

                                                                                                                                             ------from ProLights

原创粉丝点击