嘟嘟嘟




鉴于一些知道的人所知道的,不知道的人所不知道的原因,我来发NOIPday2T1的题解了。




\(O(n ^ 2)\)的做法自然很暴力,枚举断边断环为链就行了。

所以我是来讲\(O(nlogn)\)的做法的。




准确说是排序复杂度,剩下的都是\(O(n)\)的。

大体思想就是通过一遍dfs\(O(n)\)找到该断的边,然后跑一遍树输出答案就行了。




为了方便,我们把在环外并和环上节点直接相连的点称作某个点的子结点。

那么对于环上的结点\(i\)和下一个结点\(nxt[i]\),肯定是先把小于\(nxt[i]\)的\(i\)的子结点都走完了,然后判断是该走\(nxt[i]\)还是回溯(就是断边)。

回溯的话,就说明前面有一个子结点比\(nxt[i]\)小而且这个点当时又没走。

所以维护一个变量\(tp\)记录这个东西。首先要清楚的一点是如果回溯的话,那么路径上所有没走过的点都得走。然后每一次遍历点\(i\)的出边,对于所有大于\(nxt[i]\)的子结点取min。如果存在这个点,就必须要更新tp。

然后每一次判断一下,如果\(tp < nxt[i]\),就断边啦。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cmath>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<cstdlib>
  7. #include<cctype>
  8. #include<vector>
  9. #include<stack>
  10. #include<queue>
  11. using namespace std;
  12. #define enter puts("")
  13. #define space putchar(' ')
  14. #define Mem(a, x) memset(a, x, sizeof(a))
  15. #define In inline
  16. typedef long long ll;
  17. typedef double db;
  18. const int INF = 0x3f3f3f3f;
  19. const db eps = 1e-8;
  20. const int maxn = 5e5 + 5;
  21. inline ll read()
  22. {
  23. ll ans = 0;
  24. char ch = getchar(), last = ' ';
  25. while(!isdigit(ch)) last = ch, ch = getchar();
  26. while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
  27. if(last == '-') ans = -ans;
  28. return ans;
  29. }
  30. inline void write(ll x)
  31. {
  32. if(x < 0) x = -x, putchar('-');
  33. if(x >= 10) write(x / 10);
  34. putchar(x % 10 + '0');
  35. }
  36. int n, m;
  37. vector<int> v[maxn];
  38. bool in[maxn];
  39. int st[maxn], top = 0, a[maxn], cnt = 0;
  40. In bool dfs_cir(int now, int _f) //找环
  41. {
  42. st[++top] = now; in[now] = 1;
  43. for(int i = 0, to; i < (int)v[now].size(); ++i)
  44. {
  45. if((to = v[now][i]) == _f) continue;
  46. if(in[to])
  47. {
  48. while(st[top] ^ to) a[++cnt] = st[top--];
  49. a[++cnt] = st[top];
  50. return 1;
  51. }
  52. if(dfs_cir(to, now)) return 1;
  53. }
  54. in[st[top--]] = 0; return 0;
  55. }
  56. In void dfs(int now, int _f)
  57. {
  58. write(now), space;
  59. for(int i = 0, to; i < (int)v[now].size(); ++i) if((to = v[now][i]) ^ _f) dfs(to, now);
  60. }
  61. bool vis[maxn];
  62. int main()
  63. {
  64. n = read(); m = read();
  65. for(int i = 1; i <= m; ++i)
  66. {
  67. int x = read(), y = read();
  68. v[x].push_back(y); v[y].push_back(x);
  69. }
  70. for(int i = 1; i <= n; ++i) sort(v[i].begin(), v[i].end());
  71. if(m == n - 1) {dfs(1, 0); return 0;}
  72. dfs_cir(1, 0);
  73. reverse(a + 1, a + cnt + 1); //以下三条语句是判断开始往环的那一头走
  74. if(a[2] > a[cnt]) reverse(a + 2, a + cnt + 1);
  75. for(int i = 1; i <= cnt; ++i) vis[a[i]] = 1;
  76. a[cnt + 1] = a[1];
  77. for(int i = 1, tp = a[cnt]; i <= cnt; ++i)
  78. {
  79. int Min = INF;
  80. for(int j = 0, to; j < (int)v[a[i]].size(); ++j)
  81. if(!vis[to = v[a[i]][j]] && to > a[i + 1]) Min = min(Min, to);
  82. if(Min ^ INF) tp = Min;
  83. if(tp < a[i + 1] || i == cnt) //断边,直接从vector中删除元素
  84. {
  85. vector<int>::iterator it = lower_bound(v[a[i]].begin(), v[a[i]].end(), a[i + 1]);
  86. v[a[i]].erase(it);
  87. vector<int>::iterator it2 = lower_bound(v[a[i + 1]].begin(), v[a[i + 1]].end(), a[i]);
  88. v[a[i + 1]].erase(it2);
  89. break;
  90. }
  91. }
  92. dfs(1, 0);
  93. return 0;
  94. }

[NOIP2018]旅行的更多相关文章

  1. 【LG5022】[NOIP2018]旅行

    [LG5022][NOIP2018]旅行 题面 洛谷 题解 首先考虑一棵树的部分分怎么打 直接从根节点开始\(dfs\),依次选择编号最小的儿子即可 而此题是一个基环树 怎么办呢? 可以断掉环上的一条 ...

  2. 竞赛题解 - NOIP2018 旅行

    \(\mathcal {NOIP2018} 旅行 - 竞赛题解\) 坑还得一层一层的填 填到Day2T1了 洛谷 P5022 题目 (以下copy自洛谷,有删减/修改 (●ˇ∀ˇ●)) 题目描述 小 ...

  3. NOIP2018 旅行 和 赛道修建

    填很久以前的坑. 旅行 给一棵 n 个点的基环树,求字典序最小的DFS序. n ≤ 5000 题解 O(n2) 做法非常显然,枚举断掉环上哪条边然后贪心即可.当然我去年的骚操作只能得88分. O(n ...

  4. [NOIP2018]:旅行(数据加强版)(基环树+搜索+乱搞)

    题目描述 小$Y$是一个爱好旅行的$OIer$.她来到$X$国,打算将各个城市都玩一遍.小$Y$了解到,$X$国的$n$个城市之间有$m$条双向道路.每条双向道路连接两个城市.不存在两条连接同一对城市 ...

  5. NOIP2018旅行

    这道题考场上的时候暴力写RE了,我果然很菜. 看了一篇大佬的的题解才明白 dalao的题解 但是解释很少哇,为了造福人类,在下发一篇详细一点的题解. 预处理:用vector把与每个点相连的点存起来,排 ...

  6. 【比赛】NOIP2018 旅行

    发现 \(m\) 只有两种取值,于是可做了 树的直接贪心 图的枚举环上的边去掉,然后做树的贪心,搜的时候剪一下枝吧 写得有点乱 #include<bits/stdc++.h> #defin ...

  7. luogu5022 [NOIp2018]旅行 (dfs)

    m=n-1的时候,就直接贪心地dfs就可以 m=n的话,就可以枚举删掉一条边,然后照着m=n-1做 $O(n^2)$大概能过 (然而我眼瞎看不到m<=n) #include<cstdio& ...

  8. [NOIP2018]旅行(数据加强版)(图论+基环树)

    数据范围多了2个0就是不一样,O(n^2)只能68分了.(其中60分是n=m+1和原题一样的做法送的),这题直接从NOIP难度变为NOI Plus难度了不说废话直接写题解:首先dfs一遍找到环,然后和 ...

  9. 【题解】NOIP2018 旅行

    题目戳我 \(\text{Solution:}\) 首先题目描述有一点不准确:回头是必须要走完一条路无路可走的时候才能返回. 对于树的情况:显然贪心做就完事了. 对于基环树的情况:对于一个\(n\)条 ...

随机推荐

  1. 记一次IDEA编译器调优

    前言: 我们知道,IDEA是用Java写的,那么他肯定也存在虚拟机的调优的问题,那么今天我们就对它进行开刀. 下面是默认参数 位置在:C:\Program Files\JetBrains\Intell ...

  2. SpringBoot入门之Thymeleaf的使用

    在.net的MVC3 或更高版本等支持 Razor 的框架里使用cshtml,Razor是一种简单的编程语法,用于在网页中嵌入服务器端代码.在使用springboot开发mvc时也有与.net类似的视 ...

  3. S5PV210 时钟体系分析

    S5PV210 时钟体系 如下面时钟结构图所示,S5PV210 中包含 3 大类时钟域, 分别是主系统时钟域(简称 MSYS).显示相关的时钟域(简称 DSYS). 外围设备的时钟域(简称 PSYS) ...

  4. C# 数据库并发的解决方案(通用版、EF版)

    自ASP.NET诞生以来,微软提供了不少控制并发的方法,在了解这些控制并发的方法前,我们先来简单介绍下并发! 并发:同一时间或者同一时刻多个访问者同时访问某一更新操作时,会产生并发! 针对并发的处理, ...

  5. Is the “*apply” family really not vectorized?

    Question: So we are used to say to every R new user that "apply isn't vectorized, check out the ...

  6. Compiler showing 'pi' symbol on error

    Question: I was testing some code on Coliru, and I got a strange output. I went down the code and co ...

  7. 设计模式之适配器模式(Adapter)(6)

    简介 在实际的开发过程中,由于应用环境的变化(例如使用语言的变化),我们需要的实现在新的环境中没有现存对象可以满足,但是其他环境却存在这样现存的对象.那么如果将“将现存的对象”在新的环境中进行调用呢? ...

  8. Vue学习资料

    1. {{ msg }}插值表达式. v-text:将数据插入到页面中,没有闪烁问题. v-cloak:通过style属性选择器的方式display:none:防止闪烁问题. v-html:将标签解析 ...

  9. canvas-star0.html

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. 内网访问已经启动的vue项目

    1. 项目本机启动地址: http://localhost:8090/#/login 2.项目内网启动地址:  http://192.168.1.172:8090/#/login 3. 在vue项目的 ...