题目链接: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. 2017年浙工大迎新赛热身赛 L cayun日常之赏月【易错特判】

    题目描述(https://www.nowcoder.com/acm/contest/51#question) 在cayun星球月亮大小都有一个规律,月亮为每30天一个周期,在这30天的周期里,月亮的大 ...

  2. docker.[6] 数据卷

    docker.[6] 数据卷 操作指令: # docker run -v /data1:/data2 -i -t centos /bin/bash 参数说明: data1 : 这里指的是宿主机的目录( ...

  3. React 按需加载 - 代码分隔

    代码分隔 我们现在大多数React项目都是以Webpack 或者 Browserify等将一堆的jsx文件组织一起,并且由一个类似index.js的入口文件串联起来的单页面web页面. 例如: // ...

  4. web服务器与tomcat

    web服务器与tomcat 服务器分类: 硬件服务器和软件服务器 web服务器: 提供资源供别人访问 web: 网页的意思,资源. web资源分类: 动态的web资源:内容有可能发生改变的 静态的we ...

  5. class介绍

    ES6引入了Class(类)这个概念,作为对象的模板.通过class关键字,可以定义类.基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对 ...

  6. thinkphp---display与fetch区别

    区别: ① display方法直接输出模板文件渲染后的内容,fetch方法是返回模板文件渲染后的内容 ② 有时候我们不想直接输出模板内容,而是希望对内容再进行一些处理后输出, 就可以使用fetch方法 ...

  7. react-jd-index

    看见一些代码的产物,会觉得非常的漂亮~感谢无私开源的程序员们~你们是最可爱的人儿~~ //index.jsx require('./app/lib/common.css'); import React ...

  8. swiper踩过的哪些坑

    最近,苦恼于各种轮播的需求,每个自己都要自己写,写的挺烦的.终于,在网上发现了swiper插件,发现还是挺实用的,但其中还是踩过了不少的坑,其中有不少都是很简单的问题,但到发现的时候都是花了不少时间, ...

  9. Ecplise中Junit4单元测试的基本用法

    看了一些Junit4的视频,简单了解了Junit4的一些基本用法,整理记录一下. 环境搭建 这里使用的开发工具是MyEclipse,首先新建一个Java工程,将Junit4的jar包引入,eclips ...

  10. java 操作Oracle 批量入库的问题

    java 操作Oracle 批量入库的问题 先说下我运行的环境: Windows7 64位操作系统 (四核)Intel i5-2300 CPU @2.80GHz 内存4G 硬盘1T Jdk1.6+My ...