题目大意:$NOIP\;TG\;D2T1$

题解:一棵树的很简单,第一个点一定是$1$,只需要对每个节点,找最小的没有访问过的节点访问即可,我写的是$O(n\log_2n)$。

考虑基环树的部分,一个显然的想法是枚举一条环上的边,然后删掉,跑树的部分,复杂度为$O(mn\log_2n)$,明显过不了。于是考场上的我开始发扬人类智慧,发现有一个环上的边可以不经过,可以找这一条边的贡献,若不经过这条边的下一位和经过这条边的下一位进行比较,若不经过较优则不经过这条边。

出来问了一下,发现可以先把每个点的子树的儿子排序,再枚举删除的边可以做到$O(nm)$,可以过。

卡点:考试时写的代码可能会“多删除”几条边导致出错,并且仅当环上的点为当前的节点儿子中最大的节点时才会断这条边,而考场上没考虑到。考场上写了一个环的部分分,没有考虑到走回去的情况(如果不写,我的那个假的程序是可以跑对的,也就是说我白白丢了$12$分还花了时间,自闭了)

C++ Code:

#include <cstdio>
#include <algorithm>
#include <vector>
#define maxn 5010
inline int min(int a, int b) {return a < b ? a : b;} int head[maxn], cnt = 1;
struct Edge {
int to, nxt;
bool can;
} e[maxn << 1];
inline void add(int a, int b) {
e[++cnt] = (Edge) {b, head[a], true}; head[a] = cnt;
}
int n, m; namespace Work1 {
int ans[maxn], idx;
void dfs(int u, int fa = 0) {
ans[++idx] = u;
std::vector<int> V; V.clear();
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa) V.push_back(v);
}
std::sort(V.begin(), V.end());
for (std::vector<int>::iterator it = V.begin(); it != V.end(); it++) {
dfs(*it, u);
}
}
int main() {
for (int i = 1, a, b; i < n; i++) {
scanf("%d%d", &a, &b);
add(a, b);
add(b, a);
}
dfs(1);
for (int i = 1; i <= n; i++) {
printf("%d", ans[i]);
putchar(i == n ? '\n' : ' ');
}
return 0;
}
} namespace Work2 {
int C;
int ans[maxn], p[maxn], idx;
bool vis[maxn]; int res[maxn], scc;
int in_C = 0;
bool used_C = false; void dfs(int u, int fa = 0, int last = n + 1) {
vis[u] = true;
ans[++idx] = u;
std::vector<int> V; V.clear();
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (!vis[v] && v != fa) V.push_back(v);
}
std::sort(V.begin(), V.end());
for (std::vector<int>::iterator it = V.begin(); it != V.end(); it++) if (!vis[*it]) {
if (res[u] == res[*it]) {
if (in_C == u) used_C = true;
if (!in_C) in_C = u;
if (used_C) {
dfs(*it, u, n + 1);
} else {
if ((it + 1) == V.end()) {
if (*it < last) dfs(*it, u, last);
else used_C = true;
} else dfs(*it, u, *(it + 1));
}
} else dfs(*it, u, n + 1);
}
} int DFN[maxn], low[maxn];
int S[maxn], top;
void tarjan(int u, int father = 0) {
DFN[u] = low[u] = ++idx;
S[++top] = u;
int v;
for (int i = head[u]; i; i = e[i].nxt) if (i ^ father ^ 1) {
v = e[i].to;
if (!DFN[v]) {
tarjan(v, i);
low[u] = min(low[u], low[v]);
} else low[u] = min(low[u], DFN[v]);
}
if (DFN[u] == low[u]) {
scc++;
do {
v = S[top--];
res[v] = scc;
} while (v != u);
}
} inline bool check() {
for (int i = 1; i <= n; i++) if (ans[i] != p[i]) {
return p[i] < ans[i];
}
return false;
} void dfs2(int u, int fa = 0) {
p[++idx] = u;
std::vector<int> V; V.clear();
for (int i = head[u]; i; i = e[i].nxt) if (e[i].can) {
int v = e[i].to;
if (v != fa) V.push_back(v);
}
std::sort(V.begin(), V.end());
for (std::vector<int>::iterator it = V.begin(); it != V.end(); it++) {
dfs2(*it, u);
}
} int main() {
for (int i = 0, a, b; i < n; i++) {
scanf("%d%d", &a, &b);
add(a, b);
add(b, a);
}
tarjan(1);
for (int i = 1; i <= n; i++) ans[i] = n;
if (n < 500) {
for (int i = 2; i <= cnt; i += 2) {
int u = e[i ^ 1].to, v = e[i].to;
if (res[u] == res[v]) {
idx = 0;
e[i].can = e[i ^ 1].can = false;
dfs2(1);
if (check()) {
for (int j = 1; j <= n; j++) ans[j] = p[j];
}
e[i].can = e[i ^ 1].can = true;
}
}
for (int i = 1; i <= n; i++) {
printf("%d", ans[i]);
putchar(i == n ? '\n' : ' ');
}
return 0;
}
for (int i = 2; i <= cnt; i += 2) {
int u = e[i ^ 1].to, v = e[i].to;
if (res[u] == res[v]) {
C = res[u];
break;
}
}
idx = 0;
dfs(1);
for (int i = 1; i <= n; i++) {
printf("%d", ans[i]);
putchar(i == n ? '\n' : ' ');
}
return 0;
}
} int main() {
scanf("%d%d", &n, &m);
if (n - 1 == m) {
return Work1::main();
}
if (n == m) {
return Work2::main();
}
return 0;
}

  

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

  1. [NOIp2018提高组]旅行

    [NOIp2018提高组]旅行: 题目大意: 一个\(n(n\le5000)\)个点,\(m(m\le n)\)条边的连通图.可以从任意一个点出发,前往任意一个相邻的未访问的结点,或沿着第一次来这个点 ...

  2. [NOIP2018 TG D2T2]填数游戏

    题目大意:$NOIP2018\;TG\;D2T2$ 题解:在skip2004的博客基础上修改的,也是暴搜. 说明一下把vector改成数组并不可以通过此题,记录. 结论:在$m>n+1$时答案为 ...

  3. [NOIP2018 TG D1T3]赛道修建

    题目大意:$NOIP2018\;TG\;D1T3$ 题解:题目要求最短的赛道的长度最大,可以想达到二分答案,接着就是一个显然的树形$DP$. 发现对于一个点,它子树中若有两条链接起来比要求的答案大,一 ...

  4. noip 2018 d2t1 旅行

    noip 2018 d2t1 旅行 (题目来自洛谷) 给定n个城市,m条双向道路的图, 不存在两条连接同一对城市的道路,也不存在一条连接一个城市和它本身的道路.并且, 从任意一个城市出发,通过这些道路 ...

  5. @NOIP2018 - D2T1@ 旅行

    目录 @题目描述@ @题解@ @代码@ @题目描述@ 小 Y 是一个爱好旅行的 OIer.她来到 X 国,打算将各个城市都玩一遍. 小Y了解到, X国的 n 个城市之间有 m 条双向道路.每条双向道路 ...

  6. NOIp 2018 D2T1 旅行//未完成

    这个题没有认真读的话就会写下以下的DD代码 #include<bits/stdc++.h> #define N 5010 using namespace std; int n,m; int ...

  7. [NOIP2012 TG D2T1]同余方程

    题目大意:求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解. 题解:即求a在mod b意义下的逆元,这里用扩展欧几里得来解决 C++ Code: #include<cstdio ...

  8. NOIp2018 TG day1 T2暨洛谷P5020 货币系统:题解

    题目链接:https://www.luogu.org/problemnew/show/P5020 这道题感觉比较水啊,身为普及组蒟蒻都不费力的做出来了,而且数据范围应该还能大一些,n起码几万几十万都不 ...

  9. [NOIP2018 提高组] 旅行

    考虑如果我们要回溯的话,一定要把非环上的子树都搜索完. 而在环上的一个地方回溯,相当于把环上的下一个点置于所有环的顺序的最后. 所以我们只有在环上遇到环上的最大点时且周围的点都比这个点小时非正常回溯即 ...

随机推荐

  1. 在ReactNative中使用Typescript

    在ReactNative中使用Typescript 少侠放心,跟着我的这个步骤走,保你完美在RN项目中使用Typescript,废话不多说,走你 1.全局安装create-react-native-a ...

  2. 官方yum源安装选择所需版本mysql数据库并初始化(yum默认安装的是最新版MySQL8.+)

    在官网是找不到5.x系列的域名源的,系统默认是安装的oracle数据库,在安装前需要删除默认的 以下教程来源于官网说明 先去官网下载yum源,地址 https://dev.mysql.com/down ...

  3. python中字典的遍历

    用ipython运行情况如下: #新建字典 In [1]: name_cards = {'name':'sunwukong','QQ':'123124','addr':'秦皇岛'} #生成key对象 ...

  4. kudu是什么

    Apache Kudu Overview 建议配合[Apache Kudo]审阅本文(http://kudu.apache.org/overview.html) 数据模式 Kudo是一个列式存储的用于 ...

  5. 初步学习pg_control文件之十五

    接前文  初步学习pg_control文件之十四 再看如下这个: int MaxConnections; 应该说,它是一个参考值,在global.c中有如下定义 /* * Primary determ ...

  6. win10 无法修改默认程序 默认打开方式的解决方法

    此时是2018年11月24日 win10 pro 64位 版本是1803  具体版本号是17134 情景: 我的状况是.json文件的默认打开方式被新安装的应用霸占了,然后无论是通过“右键-属性-更改 ...

  7. 阴影效果的小 demo

    早上没事干,感觉字体阴影的效果还是好看的,那么就来一个小demo吧! 1.这是html 简单的有一个标签或者盒子都可以 <div class="demo11">我爱考试 ...

  8. dispaly:-webkit-box 布局中的坑

    dispaly:-webkit-box 具体用法 这里大家可以网上查, 这里说下里面的坑 里面的子对象设置-webkit-box-flex: 1 -webkit-box-flex: 2 时:一般两个子 ...

  9. 「暑期训练」「Brute Force」 Restoring Painting (CFR353D2B)

    题意 给定一定条件,问符合的矩阵有几种. 分析 见了鬼了,这破题谁加的brute force的标签,素质极差.因为范围是1e5,那你平方(枚举算法)的复杂度必然爆. 然后你就会思考其中奥妙无穷的数学规 ...

  10. Python 3基础教程25-异常处理

    在Python中,异常处理,主要是try except语句,通常语法格式如下. try: 代码块1 except Exception as e: print(e) 代码2 接着前面读取CSV文件,如果 ...