1152E - Neko and Flashback

题意:对于长为n的序列c和长为n - 1的排列p,我们可以按照如下方法得到长为n - 1的序列a,b,a',b'。

ai = min(ci, ci+1),bi = max(ci, ci+1)

a'i = ap[i],b'i = bp[i]

现在给定a'和b',求一个合法的c或者无解。

解:仔细分析性质,发现在a和b中,c除了开头和结尾会出现1次之外,每个数都会出现两次,且相邻。

我们可以把c的开头找出来,然后根据开头确定c2,然后确定c3...最后到cn

注意到这些数可能有重复的,于是我们要试图在中间插入一段。我一开始想的是链表后来发现很难写...

仔细分析,如果把a'和b'的每个位置当成边,数字当成点,就是求欧拉路。然后就没了......

关于欧拉路:就暴力DFS,把每条边都访问一次。回溯的时候把这条边入栈/把y入栈。

  1. #include <bits/stdc++.h>
  2.  
  3. const int N = ;
  4.  
  5. struct Edge {
  6. int nex, v, id, pre;
  7. }edge[N << ]; int tp = ;
  8.  
  9. int X[N], xx, a[N], b[N], cnt[N], e[N], stk[N], top, deg[N];
  10. bool vis[N];
  11.  
  12. inline void erase(int x, int i) {
  13. int nex = edge[i].nex, pre = edge[i].pre;
  14. if(e[x] == i && !nex) {
  15. e[x] = ;
  16. }
  17. else if(e[x] == i) {
  18. e[x] = nex;
  19. edge[nex].pre = ;
  20. return;
  21. }
  22. else if(!nex) {
  23. edge[pre].nex = ;
  24. }
  25. else {
  26. edge[nex].pre = pre;
  27. edge[pre].nex = nex;
  28. }
  29. edge[i].nex = edge[i].pre = ;
  30. return;
  31. }
  32.  
  33. inline void add(int x, int y, int z) {
  34. edge[++tp].v = y;
  35. edge[tp].id = z;
  36. edge[tp].nex = e[x];
  37. edge[e[x]].pre = tp;
  38. e[x] = tp;
  39. return;
  40. }
  41.  
  42. void DFS(int x) {
  43. for(int i = e[x]; i; i = edge[i].nex) {
  44. erase(x, i);
  45. int y = edge[i].v;
  46. if(vis[edge[i].id]) {
  47. continue;
  48. }
  49. vis[edge[i].id] = ;
  50. DFS(y);
  51. stk[++top] = y;
  52. }
  53. return;
  54. }
  55.  
  56. int main() {
  57.  
  58. int n;
  59. scanf("%d", &n);
  60. for(int i = ; i < n; i++) {
  61. scanf("%d", &a[i]);
  62. X[++xx] = a[i];
  63. }
  64. for(int j = ; j < n; j++) {
  65. scanf("%d", &b[j]);
  66. X[++xx] = b[j];
  67. if(b[j] < a[j]) {
  68. puts("-1");
  69. return ;
  70. }
  71. }
  72.  
  73. std::sort(X + , X + xx + );
  74. xx = std::unique(X + , X + xx + ) - X - ;
  75. for(int i = ; i < n; i++) {
  76. a[i] = std::lower_bound(X + , X + xx + , a[i]) - X;
  77. b[i] = std::lower_bound(X + , X + xx + , b[i]) - X;
  78. add(a[i], b[i], i);
  79. add(b[i], a[i], i);
  80. deg[a[i]]++;
  81. deg[b[i]]++;
  82. }
  83. int s = , pos = ;
  84. for(int i = ; i <= xx; i++) {
  85. if(deg[i] & ) {
  86. s++;
  87. pos = i;
  88. }
  89. }
  90. if(s != && s != ) {
  91. puts("-1");
  92. return ;
  93. }
  94.  
  95. DFS(pos);
  96. stk[++top] = pos;
  97. if(top != n) {
  98. puts("-1");
  99. return ;
  100. }
  101. for(int i = top; i >= ; i--) {
  102. printf("%d ", X[stk[i]]);
  103. }
  104.  
  105. return ;
  106. }

AC代码

注意复杂度,删边......

  1. #include <bits/stdc++.h>
  2.  
  3. const int N = ;
  4.  
  5. struct Edge {
  6. int nex, v, id;
  7. }edge[N << ]; int tp = ;
  8.  
  9. int X[N], xx, a[N], b[N], cnt[N], e[N], stk[N], top, deg[N];
  10. bool vis[N];
  11.  
  12. inline void add(int x, int y, int z) {
  13. edge[++tp].v = y;
  14. edge[tp].id = z;
  15. edge[tp].nex = e[x];
  16. e[x] = tp;
  17. return;
  18. }
  19.  
  20. void DFS(int x) {
  21. for(int i = e[x]; i; i = e[x]) {
  22. e[x] = edge[i].nex;
  23. int y = edge[i].v;
  24. if(vis[edge[i].id]) {
  25. continue;
  26. }
  27. vis[edge[i].id] = ;
  28. DFS(y);
  29. stk[++top] = y;
  30. }
  31. return;
  32. }
  33.  
  34. int main() {
  35.  
  36. int n;
  37. scanf("%d", &n);
  38. for(int i = ; i < n; i++) {
  39. scanf("%d", &a[i]);
  40. X[++xx] = a[i];
  41. }
  42. for(int j = ; j < n; j++) {
  43. scanf("%d", &b[j]);
  44. X[++xx] = b[j];
  45. if(b[j] < a[j]) {
  46. puts("-1");
  47. return ;
  48. }
  49. }
  50.  
  51. std::sort(X + , X + xx + );
  52. xx = std::unique(X + , X + xx + ) - X - ;
  53. for(int i = ; i < n; i++) {
  54. a[i] = std::lower_bound(X + , X + xx + , a[i]) - X;
  55. b[i] = std::lower_bound(X + , X + xx + , b[i]) - X;
  56. add(a[i], b[i], i);
  57. add(b[i], a[i], i);
  58. deg[a[i]]++;
  59. deg[b[i]]++;
  60. }
  61. int s = , pos = ;
  62. for(int i = ; i <= xx; i++) {
  63. if(deg[i] & ) {
  64. s++;
  65. pos = i;
  66. }
  67. }
  68. if(s != && s != ) {
  69. puts("-1");
  70. return ;
  71. }
  72.  
  73. DFS(pos);
  74. stk[++top] = pos;
  75. if(top != n) {
  76. puts("-1");
  77. return ;
  78. }
  79. for(int i = top; i >= ; i--) {
  80. printf("%d ", X[stk[i]]);
  81. }
  82.  
  83. return ;
  84. }

另一种删边方式

[欧拉路]CF1152E Neko and Flashback的更多相关文章

  1. 洛谷P1341 无序字母对[无向图欧拉路]

    题目描述 给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒).请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现. 输入输出格式 输入格式: 第一行输入一 ...

  2. POJ1386Play on Words[有向图欧拉路]

    Play on Words Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11846   Accepted: 4050 De ...

  3. hdu1161 欧拉路

    欧拉路径是指能从一个点出发能够“一笔画”完整张图的路径:(每条边只经过一次而不是点) 在无向图中:如果每个点的度都为偶数 那么这个图是欧拉回路:如果最多有2个奇数点,那么出发点和到达点必定为该2点,那 ...

  4. UVA10054The Necklace (打印欧拉路)

    题目链接 题意:一种由彩色珠子组成的项链.每个珠子的两半由不同的颜色组成.相邻的两个珠子在接触的地方颜色相同.现在有一些零碎的珠子,需要确定他们是否可以复原成完整的项链 分析:之前也没往欧拉路上面想, ...

  5. 洛谷 P1341 无序字母对 Label:欧拉路 一笔画

    题目描述 给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒).请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现. 输入输出格式 输入格式: 第一行输入一 ...

  6. POJ 1637 Sightseeing tour (混合图欧拉路判定)

    Sightseeing tour Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6986   Accepted: 2901 ...

  7. hihocoder 1181 欧拉路.二

    传送门:欧拉路·二 #1181 : 欧拉路·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回中小Hi和小Ho控制着主角收集了分散在各个木桥上的道具,这些道具其 ...

  8. hiho48 : 欧拉路·一

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho最近在玩一个解密类的游戏,他们需要控制角色在一片原始丛林里面探险,收集道具,并找到最后的宝藏.现在他们控制的 ...

  9. hdu5883 The Best Path(欧拉路)

    题目链接:hdu5883 The Best Path 比赛第一遍做的时候没有考虑回路要枚举起点的情况导致WA了一发orz 节点 i 的贡献为((du[i] / 2) % 2)* a[i] 欧拉回路的起 ...

随机推荐

  1. (JS)应为","

    在写cshtml的时候,vs提示:(JS)应为"," 功能无法实现,一般是因为 标点切成全角了,但是我是应为把‘’打成了“” 以下错误示范: $("ol").a ...

  2. JAVA 文件的上传下载

    一.上传文件 1.使用 transferTo 上传 @ResponseBody @RequestMapping(value = "/file/upload") public Res ...

  3. iOS疑问

    1.__NSFrozenDictionaryM在数组类簇中是什么角色?

  4. 区间dp及优化

    看了下感觉区间dp就是一种套路,直接上的板子代码就好了. 基础题ac代码:石子归并 #include<bits/stdc++.h> using namespace std; typedef ...

  5. Python sort()函数和sorted()

    1.原址排序 1)列表有自己的sort方法,其对列表进行原址排序,既然是原址排序,那显然元组不可能拥有这种方法,因为元组是不可修改的. truple无组报错: 2.副本排序 1)[:]分片方法 注意: ...

  6. oracle 如何在一个数据库创建多个实例

    实例:是一个非固定的.基于内存的基本进程与内存结构.当服务器关闭后,实例也就不存在了. 数据库(Database)指的是固定的.基于磁盘的数据文件.控制文件.日志文件.参数文件和归档日志文件等. 一般 ...

  7. 2019-5-29-Roslyn-让-VisualStudio-急速调试底层库方法

    title author date CreateTime categories Roslyn 让 VisualStudio 急速调试底层库方法 lindexi 2019-5-29 20:2:9 +08 ...

  8. telnet- Linux必学的60个命令

    1.作用 telnet表示开启终端机阶段作业,并登入远端主机.telnet是一个Linux命令,同时也是一个协议(远程登陆协议). 2.格式 telnet [-8acdEfFKLrx][-b][-e] ...

  9. keepalived的常见的健康检查方式

    TCP_CHECK tcp端口检测 HTTP_GET http接口检测 MISC_CHECK 自定义脚本检测 tcp端口检测 TCP_CHECK { connect_port 80 connect_t ...

  10. CVE-2016-0095提权漏洞分析

    1 前言 瞻仰了k0shl和鹏哥 的漏洞分析,感慨万千,任重而道远. 2 系统环境和工具 windows 7 32旗舰版 windbg 3 poc 3.1poc复现 首先k0shl大佬给出的poc() ...