[NOIP2018]旅行
嘟嘟嘟
鉴于一些知道的人所知道的,不知道的人所不知道的原因,我来发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]\),就断边啦。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 5e5 + 5;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
int n, m;
vector<int> v[maxn];
bool in[maxn];
int st[maxn], top = 0, a[maxn], cnt = 0;
In bool dfs_cir(int now, int _f) //找环
{
st[++top] = now; in[now] = 1;
for(int i = 0, to; i < (int)v[now].size(); ++i)
{
if((to = v[now][i]) == _f) continue;
if(in[to])
{
while(st[top] ^ to) a[++cnt] = st[top--];
a[++cnt] = st[top];
return 1;
}
if(dfs_cir(to, now)) return 1;
}
in[st[top--]] = 0; return 0;
}
In void dfs(int now, int _f)
{
write(now), space;
for(int i = 0, to; i < (int)v[now].size(); ++i) if((to = v[now][i]) ^ _f) dfs(to, now);
}
bool vis[maxn];
int main()
{
n = read(); m = read();
for(int i = 1; i <= m; ++i)
{
int x = read(), y = read();
v[x].push_back(y); v[y].push_back(x);
}
for(int i = 1; i <= n; ++i) sort(v[i].begin(), v[i].end());
if(m == n - 1) {dfs(1, 0); return 0;}
dfs_cir(1, 0);
reverse(a + 1, a + cnt + 1); //以下三条语句是判断开始往环的那一头走
if(a[2] > a[cnt]) reverse(a + 2, a + cnt + 1);
for(int i = 1; i <= cnt; ++i) vis[a[i]] = 1;
a[cnt + 1] = a[1];
for(int i = 1, tp = a[cnt]; i <= cnt; ++i)
{
int Min = INF;
for(int j = 0, to; j < (int)v[a[i]].size(); ++j)
if(!vis[to = v[a[i]][j]] && to > a[i + 1]) Min = min(Min, to);
if(Min ^ INF) tp = Min;
if(tp < a[i + 1] || i == cnt) //断边,直接从vector中删除元素
{
vector<int>::iterator it = lower_bound(v[a[i]].begin(), v[a[i]].end(), a[i + 1]);
v[a[i]].erase(it);
vector<int>::iterator it2 = lower_bound(v[a[i + 1]].begin(), v[a[i + 1]].end(), a[i]);
v[a[i + 1]].erase(it2);
break;
}
}
dfs(1, 0);
return 0;
}
[NOIP2018]旅行的更多相关文章
- 【LG5022】[NOIP2018]旅行
[LG5022][NOIP2018]旅行 题面 洛谷 题解 首先考虑一棵树的部分分怎么打 直接从根节点开始\(dfs\),依次选择编号最小的儿子即可 而此题是一个基环树 怎么办呢? 可以断掉环上的一条 ...
- 竞赛题解 - NOIP2018 旅行
\(\mathcal {NOIP2018} 旅行 - 竞赛题解\) 坑还得一层一层的填 填到Day2T1了 洛谷 P5022 题目 (以下copy自洛谷,有删减/修改 (●ˇ∀ˇ●)) 题目描述 小 ...
- NOIP2018 旅行 和 赛道修建
填很久以前的坑. 旅行 给一棵 n 个点的基环树,求字典序最小的DFS序. n ≤ 5000 题解 O(n2) 做法非常显然,枚举断掉环上哪条边然后贪心即可.当然我去年的骚操作只能得88分. O(n ...
- [NOIP2018]:旅行(数据加强版)(基环树+搜索+乱搞)
题目描述 小$Y$是一个爱好旅行的$OIer$.她来到$X$国,打算将各个城市都玩一遍.小$Y$了解到,$X$国的$n$个城市之间有$m$条双向道路.每条双向道路连接两个城市.不存在两条连接同一对城市 ...
- NOIP2018旅行
这道题考场上的时候暴力写RE了,我果然很菜. 看了一篇大佬的的题解才明白 dalao的题解 但是解释很少哇,为了造福人类,在下发一篇详细一点的题解. 预处理:用vector把与每个点相连的点存起来,排 ...
- 【比赛】NOIP2018 旅行
发现 \(m\) 只有两种取值,于是可做了 树的直接贪心 图的枚举环上的边去掉,然后做树的贪心,搜的时候剪一下枝吧 写得有点乱 #include<bits/stdc++.h> #defin ...
- luogu5022 [NOIp2018]旅行 (dfs)
m=n-1的时候,就直接贪心地dfs就可以 m=n的话,就可以枚举删掉一条边,然后照着m=n-1做 $O(n^2)$大概能过 (然而我眼瞎看不到m<=n) #include<cstdio& ...
- [NOIP2018]旅行(数据加强版)(图论+基环树)
数据范围多了2个0就是不一样,O(n^2)只能68分了.(其中60分是n=m+1和原题一样的做法送的),这题直接从NOIP难度变为NOI Plus难度了不说废话直接写题解:首先dfs一遍找到环,然后和 ...
- 【题解】NOIP2018 旅行
题目戳我 \(\text{Solution:}\) 首先题目描述有一点不准确:回头是必须要走完一条路无路可走的时候才能返回. 对于树的情况:显然贪心做就完事了. 对于基环树的情况:对于一个\(n\)条 ...
随机推荐
- ubuntu server 14.04 LTS下搭建LAMP环境之最详细笔记之一U盘安装双系统
前言: 一直在WIN上使用PHP,不喜欢用WAMP,每次都是手动在windows配置环境,偶尔有一次装了小红帽玩了两天,感觉不是很习惯就换了回来,过了没几天见讨论LAMP环境,于是安装了ubuntu的 ...
- [转]angular2封装material2对话框组件
本文转自:https://www.jianshu.com/p/da9978e25566 1. 说明 angular-material2自身文档不详,控件不齐,使用上造成了很大的障碍.这里提供一个方案用 ...
- T-SQL :TOP和OFFSET-FETCH筛选 (五)
通过were和having条件可以对数据进行筛选,那么如何通过排序对数据进行筛选呢? 1.TOP筛选 用于限制查询返回行数或者行数的百分比. 例如 我们对订单表筛选最近产生的订单5条 ) orderi ...
- JavaSE-基础语法(一)--数据类型及包装类
一.JavaSE-基础语法(一) 一.数据类型 二.变量常量 三.流程控制语句 四.数组 一.数据类型 java语言的数据类型包括两种,基本数据类型和引用数据类型. (1).基本数据类型:变量名指向具 ...
- 详解promise、async和await的执行顺序
1.题目和答案 一道题题目:下面这段promise.async和await代码,请问控制台打印的顺序? async function async1(){ console.log('async1 sta ...
- 23种设计模式+J2EE设计模式学习笔记-初识设计模式
设计模式简介: 设计模式是一套被反复使用的.多数人知晓的.经过分类编目的.代码设计经验的总结.(个人理解:设计模式是不关乎业务,逻辑实现,针对普遍问题的一种解决方案). 设计模式的类型: 传统23种设 ...
- linux学习笔记-软件包的相关知识
我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 一.软件包种类 1.源码包 源码包即提供源代码的发行包 2.二进制包 二进制包即提供二进制文件的发行包 安装方法查找二进制包官网 ...
- 理解微信小程序Wepy框架的三个事件交互$broadcast,$emit,$invoke
$broadcast: $broadcast事件是由父组件发起,所有子组件都会收到此广播事件,除非事件被手动取消.事件广播的顺序为广度优先搜索顺序,如上图,如果页面Page_Index发起一个$bro ...
- 【读书笔记】iOS-开发者证书
虽然使用通配符听起来很赞,但问题是使用这种App ID的应用无法使用苹果的Push Notification服务以及应用内支付服务. 如果你有钱的话,建议单独买一个设备用于开发,将来你可能会安装iOS ...
- 【读书笔记】iOS-Apple的移动设备硬件
本书中有一个关键观点是:“硬件并不是特别重要,用户体验才是真正的杀手级应用.“尽管如此,多了解一些你使用的硬件的相关知识,对于整个项目来说是必备的,而对于设计和开发高质量的作品来说敢是不可或缺的. 人 ...