题目链接:https://www.luogu.org/problem/P5022

这道题目一开始看的时候没有思路,但是看到数据范围里面有一个:

\(m = n-1\) 或 \(m = n\) ,一下子有了思路。

当 \(m = n-1\) 时,这就是一棵树,以1为根节点进行搜索,每次优先访问编号小的点即可。

当 \(m = n\) 时,可知只有一个环,找到环中对应的所有边,然后遍历每一条环中的边,假设删除它,然后就变成了一棵树。

时间复杂度为:\(O(n^2)\) 。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5050;
struct Node {
int u, v, id;
Node() {}
Node(int _u, int _v, int _id) { u = _u; v = _v; id = _id; }
} edge[maxn*2], loop_edge[maxn];
vector<Node> g[maxn];
int n, m, p[maxn], pe[maxn], cnt, depth[maxn];
bool vis[maxn], vise[maxn*2], marked[maxn*2];
int ans_seq[maxn], tmp_seq[maxn], ans_cnt, tmp_cnt;
bool cmp(Node a, Node b) {
return a.v < b.v;
} void find_loop(int u, int pre, int d) {
vis[u] = true;
depth[u] = d;
int sz = g[u].size();
for (int i = 0; i < sz; i ++) {
int v = g[u][i].v, id = g[u][i].id;
if (v == pre) continue;
if (!vis[v]) {
vise[id] = vise[id^1] = true;
p[v] = u;
pe[v] = id;
find_loop(v, u, d+1);
}
}
} void select_loop_edges(int u, int v, int id) {
loop_edge[cnt++] = Node(u, v, id);
while (u != v) {
if (depth[u] > depth[v]) {
loop_edge[cnt++] = Node(p[u], u, pe[u]);
u = p[u];
}
else if (depth[u] < depth[v]) {
loop_edge[cnt++] = Node(p[v], v, pe[v]);
v = p[v];
}
else {
loop_edge[cnt++] = Node(p[u], u, pe[u]);
u = p[u];
loop_edge[cnt++] = Node(p[v], v, pe[v]);
v = p[v];
}
}
} void dfs(int u, int pre) {
tmp_seq[tmp_cnt++] = u;
int sz = g[u].size();
for (int i = 0; i < sz; i ++) {
int v = g[u][i].v, id = g[u][i].id;
if (v == pre || marked[id] || marked[id^1]) continue;
dfs(v, u);
}
} void final_check() {
bool flag = false;
if (ans_seq[0]) {
for (int i = 0; i < n; i ++) {
if (ans_seq[i] > tmp_seq[i]) { flag = true; break; }
else if (ans_seq[i] < tmp_seq[i]) break;
}
}
else
flag = true;
if (flag) for (int i = 0; i < n; i ++) ans_seq[i] = tmp_seq[i];
} int main() {
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i ++) {
int u, v, w;
scanf("%d%d", &u, &v);
g[u].push_back(Node(u, v, i*2));
g[v].push_back(Node(v, u, i*2+1));
edge[i*2] = Node(u, v, i*2);
edge[i*2+1] = Node(v, u, i*2+1);
}
for (int i = 1; i <= n; i ++) sort(g[i].begin(), g[i].end(), cmp);
if (m == n) {
find_loop(1, -1, 1);
for (int i = 0; i < 2*m; i += 2) {
if (!vise[i]) {
int u = edge[i].u, v = edge[i].v;
select_loop_edges(u, v, i);
break;
}
}
for (int i = 0; i < cnt; i ++) {
marked[loop_edge[i].id] = marked[loop_edge[i].id^1] = true;
tmp_cnt = 0;
dfs(1, -1);
final_check();
marked[loop_edge[i].id] = marked[loop_edge[i].id^1] = false;
}
}
else { // m == n-1
dfs(1, -1);
final_check();
}
for (int i = 0; i < n; i ++) {
if (i) putchar(' ');
printf("%d", ans_seq[i]);
}
puts("");
return 0;
}

洛谷P5022 旅行 题解 去环/搜索的更多相关文章

  1. 洛谷 P5022 旅行——题解

    发现大部分题解都是O(n^2)的复杂度,这里分享一个O(n)复杂度的方法. 题目传送 首先前60%的情况,图是一棵无根树,只要从1开始DFS,每次贪心走点的编号最小的点就行了.(为什么?因为当走到一个 ...

  2. 洛谷P5022 旅行 题解

    前面几个代码都是部分分代码,最后一个才是AC了的,所以最后一个有详细注释 安利一发自己的Blog 这是提高组真题,233有点欧拉回路的感觉. 题目大意: 一个 连通 图,双向边 ,无重边 , 访问图中 ...

  3. 洛谷 P5022 旅行

    今天换标题格式了,因为感觉原版实在有点别扭…… 还是直接上题板,看完题再讲吧: 对了有个小细节没说,m一定是等于n或者等于n-1的. 这题是2018年提高组的真题哦!被我肝了2天肝出来了,2天……(真 ...

  4. 洛谷P2827 蚯蚓 题解

    洛谷P2827 蚯蚓 题解 题目描述 本题中,我们将用符号 ⌊c⌋ 表示对 c 向下取整. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现 ...

  5. 洛谷NOIp热身赛题解

    洛谷NOIp热身赛题解 A 最大差值 简单树状数组,维护区间和.区间平方和,方差按照给的公式算就行了 #include<bits/stdc++.h> #define il inline # ...

  6. 洛谷P1816 忠诚 题解

    洛谷P1816 忠诚 题解 题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意.但是由于一些人 ...

  7. 洛谷P1378 油滴扩展(搜索)

    洛谷P1378 油滴扩展 直接暴力搜索更新答案就可以了. 时间复杂度为 \(O(n!)\) . #include<stdio.h> #include<stdlib.h> #in ...

  8. 随手练——洛谷-P1008 / P1618 三连击(暴力搜索)

    1.普通版 第一眼看到这个题,我脑海里就是,“我们是不是在哪里见过~”,去年大一刚学C语言的时候写过一个类似的题目,写了九重循环....就像这样(在洛谷题解里看到一位兄台写的....超长警告,慎重点开 ...

  9. [CodePlus 2017 11月赛&洛谷P4058]木材 题解(二分答案)

    [CodePlus 2017 11月赛&洛谷P4058]木材 Description 有 n棵树,初始时每棵树的高度为 Hi ,第 i棵树每月都会长高 Ai.现在有个木料长度总量为 S的订单, ...

随机推荐

  1. python 从数据库取回来的数据中文显示为乱码

    问题:从数据库取回来的数据,中文显示为乱码. 解决办法: 此处要指定charset为utf-8(一般数据库编码都是utf8),否则读取出的中文会乱码

  2. DirectX11笔记(八)--Direct3D渲染4--VERTEX SHADER

    原文:DirectX11笔记(八)--Direct3D渲染4--VERTEX SHADER 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u0103 ...

  3. 深入浅出Javascript闭包

    一.引子 闭包(closure)是 Javascript 语言的一个难点,面试时常被问及,也是它的特色,很多高级应用都要依靠闭包实现.本文尽可能用简单易懂的话,讲清楚闭包的概念.形成条件及其常见的面试 ...

  4. Linux用户程序配置文件

    在 Linux(和一般的 UNIX)中,有无数的“用户”程序.最常见的一种用户程序配置文件是 /etc/lynx.cfg.这是著名的文本浏览器 lynx 的配置文件.通过这个文件,您可以定义代理服务器 ...

  5. PAT天梯赛L3-011 直捣黄龙

    题目链接:点击打开链接 本题是一部战争大片 -- 你需要从己方大本营出发,一路攻城略地杀到敌方大本营.首先时间就是生命,所以你必须选择合适的路径,以最快的速度占领敌方大本营.当这样的路径不唯一时,要求 ...

  6. 盘点Apache毕业的11个顶级项目

    自1999年成立至今,Apache 软件基金会已成功建立起自己强大的生态圈.其社区涌现了非常多优秀的开源项目,同时有越来越多国内外项目走向这个国际开源社区进行孵化.据悉,目前所有的 Apache 项目 ...

  7. 2019-8-31-asp-dotnet-core-支持客户端上传文件

    title author date CreateTime categories asp dotnet core 支持客户端上传文件 lindexi 2019-08-31 16:55:58 +0800 ...

  8. 运行docker容器镜像2(指定容器启动时启动的脚本)

    docker中启动容器有以下两种情况. 第一种是通过 # docker run containerid 启动一个容器. 第二种是重新启动已经关闭的容器. # docker start containe ...

  9. PHP汉字验证码

    转自:http://www.blhere.com/1167.html 12345678910111213141516171819202122232425262728293031323334353637 ...

  10. [React Native]升级React Native版本

    React Native正式版本还没发布,但是小版本基本上每个月都更新1-2次.9月11号又更新了0.33版本,其中有两个增强功能正好是项目中用到的. 添加Android6.0权限验证API Add ...