[GDKOI 2015] 青蛙跳环

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[GDKOI 2015] 青蛙跳环相关的知识,希望对你有一定的参考价值。

题意

  给定 n 个标号为 0, 1, 2, ..., n-1 的点.

  一只青蛙在点 i 能够跳往 (2 * i) % n 和 (2 * i + 1) % n .

  若该青蛙从点 0 出发, 是否能够跳出一条哈密顿回路, 如果可以, 还要找到字典序最大的.

  2 <= N <= 10000 .

 

分析

  我们先研究一些小的情形.

  暴力打表发现, 当 n 为奇数时, 一定无解.

  接下来保证 n 为偶数.

 

  当 n 为偶数时, 2 * (n / 2) = 0 (mod n) .

  所以 i 和 i + n / 2 能够跳到的点是相同的, 我们考虑把它们缩点.

  以 n = 8 为例, 画出这样一个图.

          ----------------------------------------         

          ↓             ↑

         ---------    --------     --------    ---------

   ←←←   | 0 |    | 1 | <-  | 2 |     |  3 |      →→→

   |        |    |  ->   |    | -> |    | <-   |    |       |

   →→→   | 4 |    | 5 |   | 6 |     | 7 |   ←←←

         ---------    ----------   --------    ----------

                  ↓             ↑

                  ----------------------------------------

  发现每个点不仅有且仅有两条出边, 而且有且仅有两条入边.

  而我们的目标是每个点经过两次, 所以我们的目标相当于是经过所有的边, 直接求欧拉回路.

 

实现

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cctype>
 5 
 6 const int N = 10005;
 7 
 8 int n, Lis[N], tot;
 9 bool v[N];
10 
11 void Dfs(int x) {
12     if (!v[x << 1 | 1]) {
13         v[x << 1 | 1] = true;
14         Dfs((x << 1 | 1) % (n >> 1));
15         Lis[++tot] = x << 1 | 1;
16     }
17     if (!v[x << 1]) {
18         v[x << 1] = true;
19         Dfs((x << 1) % (n >> 1));
20         Lis[++tot] = x << 1;
21     }
22 }
23 
24 int main(void) {
25     #ifndef ONLINE_JUDGE
26         freopen("frog.in", "r", stdin);
27     #endif
28     
29     scanf("%d", &n);
30     if (n & 1) return puts("-1"), 0;
31     
32     Dfs(0), Lis[++tot] = 0;
33     while (tot > 0) printf("%d ", Lis[tot--]); puts("");
34     
35     return 0;
36 }

 

以上是关于[GDKOI 2015] 青蛙跳环的主要内容,如果未能解决你的问题,请参考以下文章

GDKOI2018酱油记

GDKOI 2018 酱油记

bzoj1854: [Scoi2010]游戏(匈牙利) / GDKOI Day2 T2(最大流)

GDKOI2018游记

GDKOI游记

GDKOI2018游记