洛谷P5022 旅行 题解 去环/搜索
题目链接: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 旅行 题解 去环/搜索的更多相关文章
- 洛谷 P5022 旅行——题解
发现大部分题解都是O(n^2)的复杂度,这里分享一个O(n)复杂度的方法. 题目传送 首先前60%的情况,图是一棵无根树,只要从1开始DFS,每次贪心走点的编号最小的点就行了.(为什么?因为当走到一个 ...
- 洛谷P5022 旅行 题解
前面几个代码都是部分分代码,最后一个才是AC了的,所以最后一个有详细注释 安利一发自己的Blog 这是提高组真题,233有点欧拉回路的感觉. 题目大意: 一个 连通 图,双向边 ,无重边 , 访问图中 ...
- 洛谷 P5022 旅行
今天换标题格式了,因为感觉原版实在有点别扭…… 还是直接上题板,看完题再讲吧: 对了有个小细节没说,m一定是等于n或者等于n-1的. 这题是2018年提高组的真题哦!被我肝了2天肝出来了,2天……(真 ...
- 洛谷P2827 蚯蚓 题解
洛谷P2827 蚯蚓 题解 题目描述 本题中,我们将用符号 ⌊c⌋ 表示对 c 向下取整. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现 ...
- 洛谷NOIp热身赛题解
洛谷NOIp热身赛题解 A 最大差值 简单树状数组,维护区间和.区间平方和,方差按照给的公式算就行了 #include<bits/stdc++.h> #define il inline # ...
- 洛谷P1816 忠诚 题解
洛谷P1816 忠诚 题解 题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意.但是由于一些人 ...
- 洛谷P1378 油滴扩展(搜索)
洛谷P1378 油滴扩展 直接暴力搜索更新答案就可以了. 时间复杂度为 \(O(n!)\) . #include<stdio.h> #include<stdlib.h> #in ...
- 随手练——洛谷-P1008 / P1618 三连击(暴力搜索)
1.普通版 第一眼看到这个题,我脑海里就是,“我们是不是在哪里见过~”,去年大一刚学C语言的时候写过一个类似的题目,写了九重循环....就像这样(在洛谷题解里看到一位兄台写的....超长警告,慎重点开 ...
- [CodePlus 2017 11月赛&洛谷P4058]木材 题解(二分答案)
[CodePlus 2017 11月赛&洛谷P4058]木材 Description 有 n棵树,初始时每棵树的高度为 Hi ,第 i棵树每月都会长高 Ai.现在有个木料长度总量为 S的订单, ...
随机推荐
- 第十章—DOM(一)——Document类型
DOCUMENT类型 JS通过document类型表示文档,在文档中document对象是HTMLDocument的一个实例,表示整个HTML页面.document对象是window对象的一个属性,因 ...
- git update-index --assume-unchanged忽略跟踪
Git 忽略已跟踪文件的改动 git update-index --assume-unchanged Git之本地忽略 这个分两种情况: 本地永久忽略,效果的gitignore一样,只不过不适于写到g ...
- python GBK
- IMEI校验思路及代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Python中的简单实现UDP协议没有粘包问题
服务端: import socket server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #数据报协议->udp server.bind ...
- Kafka 简易教程
1.初识概念 Apache Kafka是一个分布式消息发布订阅系统. TopicKafka将消息种子(Feed)分门别类, 每一类的消息称之为话题(Topic). Producer发布消息的对象称之为 ...
- 设置WPF窗口相对于非WPF窗口的位置
原文:设置WPF窗口相对于非WPF窗口的位置 在前一个Post当中,指出了在WPF的WindowInteropHelper类中的一个BUG:通过WindowInteropHelper的Owner属性不 ...
- 2019-7-20-win10-uwp-使用-msbuild-命令行编译-UWP-程序
title author date CreateTime categories win10 uwp 使用 msbuild 命令行编译 UWP 程序 lindexi 2019-07-20 21:56:2 ...
- 2018-7-9-dotnet-设计规范-·-数组定义
title author date CreateTime categories dotnet 设计规范 · 数组定义 lindexi 2018-07-09 14:26:48 +0800 2018-2- ...
- HDU-1257_最少拦截系统
最少拦截系统 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Problem Desc ...