题目大意:$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. 【linux基于Postfix和Dovecot邮件系统的搭建】

    一:PostFixe和Dovecot的简单介绍 Postfix postfix是Wietse Venema在IBM的GPL协议之下开发的MTA(邮件传输代理)软件.postfix是Wietse Ven ...

  2. 其他乱七八糟的css

    white-space:normal; word-break:break-all;字母数字强制换行表格宽度失效给上table-layout:fixed(display: table-cell;此元素会 ...

  3. Yii2.0 游客访问限制(转)

    最近在用Yii2.0做项目,其中需要实现一个功能:没有登录不能访问部分页面,即游客身份访问限制.查了半天资料,终于找到答案.解决方法如下: 在access里,access即访问的意思,其中有个配置项 ...

  4. css文本截字,超出文本省略号显示

    一.单行文本截字 p { text-overflow: ellipsis;/*显示省略号代替裁剪的文本*/ white-space: nowrap;/*空白处理方式 不换行*/ overflow: h ...

  5. Centos7 搭建 hadoop3.1.1 集群教程

    配置环境要求: Centos7 jdk 8 Vmware 14 pro hadoop 3.1.1 Hadoop下载 安装4台虚拟机,如图所示 克隆之后需要更改网卡选项,ip,mac地址,uuid 重启 ...

  6. Nginx一直报504超时,配置相关参数好了

    相关参数:large_client_header_buffers 4 16k;client_max_body_size 30m;client_body_buffer_size 128k;proxy_c ...

  7. [Python 3.X]python练习笔记[2]-----用python实现七段数码管显示年月日

    #SevenDigitsDrawV2.py import turtle import time def drawGap(i):#绘制数码管间隔 turtle.penup() turtle.fd(i) ...

  8. Oralce 的sql问题

    获取两个日期间的工作日, SQL> select dt_time  2    from (select to_date('01-12-2010 08:20:56','dd-mm-yyyy HH: ...

  9. crontab时间规则

    sudo crontab -e 5 * * * *每小时第5分钟执行*/5 * * * *每5分钟执行0 2 * * * 每天凌晨2点执行 cron是一个linux下的定时执行工具,可以在无需人工干预 ...

  10. Android Studio引入AAR文件

    一.编译生成AAR文件 二.把AAR文件复制到项目的libs目录下 三.在项目的配置文件中加入如下代码: android { //other code repositories{ flatDir{ d ...