NOIP2018旅行
这道题考场上的时候暴力写RE了,我果然很菜。
看了一篇大佬的的题解才明白 dalao的题解
但是解释很少哇,为了造福人类,在下发一篇详细一点的题解。
预处理:用vector把与每个点相连的点存起来,排一遍序。
m=n-1的情况
这种比较好处理,搜到一个节点后找一个与该节点相连的最小的编号的儿子继续往下搜,显然这样答案更优。不过要小心RE。
具体代码就是:
void work(int u,int fa)
{
if(vis[u]) return ;
vis[u]=1;
ans[++dep]=u;
for(int i=0;i<vec[u].size();++i)
{
int v=vec[u][i];
if(v==fa)
continue;
work(v,u);
}
}
比较简单一点的深搜的板子。
m=n的情况
基环树的情况不太好处理。但是基环树只有一个环,如果删去一条环上的边,那么就会变成一棵树。所以我们就暴力地枚举删哪条边,将所有答案求一个最优值。代码在洛谷上跑了900多毫秒,感觉有点虚……
不过有一个比较高效的优化:如果边不在环上,就不用搜了,因为在树上的边一定是要经过的。(可惜我不会...)
在主函数里特判一下:
if(n==m)
{
for(int i=0;i<tot;i+=2)//因为加的是双向边,所以i+=2
//如果你习惯tot从一开始,循环写成这样:for(int i=1;i<=tot;i+=2),恭喜你得到TLE的好成绩
{
dep=0; x=e[i].u; y=e[i].v;//x,y记录一下当前搜到的边
memset(vis,0,sizeof(vis));
dfs(1,-1);
if(dep<n) continue;//说明枚举到的边不在环上
if(ans[1]==0)
change();//统计答案
else if(check()) change();//check比较哪个答案更优
}
for(int i=1;i<=n;++i)
printf("%d ",ans[i]);
return 0;
}
当然vector是比较慢的,可是我也不会优化.......
完整代码奉上:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int n,m,ans[5050],tot,head[5050];
int k[5050],dep,x,y;
bool vis[5050];
vector <int> vec[5050];
struct edge{
int u,v,next;
}e[10005];
void add(int x,int y)
{
e[tot].u=x;
e[tot].v=y;
e[tot].next=head[x];
head[x]=tot++;
}
inline int read()
{
int ans=0,w=1;
char c=getchar();
while((c<'0'||c>'9')&&c!='-') c=getchar();
if(c=='-') { w=-1; c=getchar();};
while(c>='0'&&c<='9')
{ ans=ans*10+c-'0'; c=getchar(); }
return ans*w;
}
void dfs(int u,int fa)
{
if(vis[u]) return;
vis[u]=1;
k[++dep]=u;
for(int i=0;i<vec[u].size();++i)
{
int v=vec[u][i];
if(v==fa) continue;
if((v==y&&u==x)||(v==x&&u==y))
continue;
dfs(v,u);
}
}
bool check()
{
for(int i=1;i<=n;++i)
{
if(k[i]==ans[i])
continue;
if(k[i]>ans[i])
return false;
else return true;
}
}
void change()
{
for(int i=1;i<=n;++i)
ans[i]=k[i];
}
void work(int u,int fa)
{
if(vis[u]) return ;
vis[u]=1;
ans[++dep]=u;
for(int i=0;i<vec[u].size();++i)
{
int v=vec[u][i];
if(v==fa)
continue;
work(v,u);
}
}
int main()
{
int u,v;
memset(head,-1,sizeof(head));
n=read(); m=read();
for(int i=1;i<=m;++i)
{
u=read(); v=read();
vec[u].push_back(v);
vec[v].push_back(u);
add(u,v); add(v,u);
}
for(int i=1;i<=n;++i)
sort(vec[i].begin(),vec[i].end());
if(n==m)
{
for(int i=0;i<tot;i+=2)
{
dep=0; x=e[i].u; y=e[i].v;
memset(vis,0,sizeof(vis));
dfs(1,-1);
if(dep<n) continue;
if(ans[1]==0)
change();
else if(check()) change();
}
for(int i=1;i<=n;++i)
printf("%d ",ans[i]);
return 0;
}
work(1,-1);
for(int i=1;i<=n;++i)
printf("%d ",ans[i]);
return 0;
}
NOIP2018旅行的更多相关文章
- 【LG5022】[NOIP2018]旅行
[LG5022][NOIP2018]旅行 题面 洛谷 题解 首先考虑一棵树的部分分怎么打 直接从根节点开始\(dfs\),依次选择编号最小的儿子即可 而此题是一个基环树 怎么办呢? 可以断掉环上的一条 ...
- 竞赛题解 - NOIP2018 旅行
\(\mathcal {NOIP2018} 旅行 - 竞赛题解\) 坑还得一层一层的填 填到Day2T1了 洛谷 P5022 题目 (以下copy自洛谷,有删减/修改 (●ˇ∀ˇ●)) 题目描述 小 ...
- NOIP2018 旅行 和 赛道修建
填很久以前的坑. 旅行 给一棵 n 个点的基环树,求字典序最小的DFS序. n ≤ 5000 题解 O(n2) 做法非常显然,枚举断掉环上哪条边然后贪心即可.当然我去年的骚操作只能得88分. O(n ...
- [NOIP2018]:旅行(数据加强版)(基环树+搜索+乱搞)
题目描述 小$Y$是一个爱好旅行的$OIer$.她来到$X$国,打算将各个城市都玩一遍.小$Y$了解到,$X$国的$n$个城市之间有$m$条双向道路.每条双向道路连接两个城市.不存在两条连接同一对城市 ...
- 【比赛】NOIP2018 旅行
发现 \(m\) 只有两种取值,于是可做了 树的直接贪心 图的枚举环上的边去掉,然后做树的贪心,搜的时候剪一下枝吧 写得有点乱 #include<bits/stdc++.h> #defin ...
- luogu5022 [NOIp2018]旅行 (dfs)
m=n-1的时候,就直接贪心地dfs就可以 m=n的话,就可以枚举删掉一条边,然后照着m=n-1做 $O(n^2)$大概能过 (然而我眼瞎看不到m<=n) #include<cstdio& ...
- [NOIP2018]旅行(数据加强版)(图论+基环树)
数据范围多了2个0就是不一样,O(n^2)只能68分了.(其中60分是n=m+1和原题一样的做法送的),这题直接从NOIP难度变为NOI Plus难度了不说废话直接写题解:首先dfs一遍找到环,然后和 ...
- [NOIP2018]旅行
嘟嘟嘟 鉴于一些知道的人所知道的,不知道的人所不知道的原因,我来发NOIPday2T1的题解了. \(O(n ^ 2)\)的做法自然很暴力,枚举断边断环为链就行了. 所以我是来讲\(O(nlogn)\ ...
- 【题解】NOIP2018 旅行
题目戳我 \(\text{Solution:}\) 首先题目描述有一点不准确:回头是必须要走完一条路无路可走的时候才能返回. 对于树的情况:显然贪心做就完事了. 对于基环树的情况:对于一个\(n\)条 ...
随机推荐
- OracleSql语句学习(一)
--SQL语句本身是不区分大小写的,每个关键字用空格隔开,为了增加可读性,退出所有关键字--全部大写,非关键字都小写SELECT SYSDATE FROM dual--创建表CREATE TABLE ...
- MySQL8.0-NoSQL和SQL的对比及MySQL的优势
一.SQL VS NoSQL SQL:关系型数据库,用SQL语句来操作数据 NOSQL:非关系型数据库,NoSQL的含义是不仅仅有SQL,而实际上大多数NoSQL不用SQL来操作数据 常见的关系型数据 ...
- 04 | 链表(上):如何实现LRU缓存淘汰算法?
今天我们来聊聊“链表(Linked list)”这个数据结构.学习链表有什么用呢?为了回答这个问题,我们先来讨论一个经典的链表应用场景,那就是+LRU+缓存淘汰算法. 缓存是一种提高数据读取性能的技术 ...
- 比sun.misc.Encoder()/Decoder()的base64更高效的mxBase64算法
package com.mxgraph.online; import java.util.Arrays; /** A very fast and memory efficient class to e ...
- iOS高德地图让指定区域或者点显示在屏幕中间
对于高德地图也是一个新手,很多功能看文档,问技术 或者高德群里讨论 群号:204668425 在我们需求中绘制的有 圆 折线 不规则图形 方式,打开地图指定的绘制图形置于屏幕中间 1.首先创建一个数 ...
- 下载图片没有关闭http输入流导致下载超时
在某次接入第三方厂商数据时,需要根据对方提供的URL地址下载图片,当数据量大时会遇到很多的下载图片超时问题,开始以为是第三方厂商的问题,对方排查了很久之后,说是我这边下载数据全部留在缓存区,导致缓存区 ...
- Tesseract-ocr 安装与使用
Tesseract(识别引擎),一款由HP实验室开发由Google维护的开源OCR(Optical Character Recognition , 光学字符识别)引擎,与Microsoft Offic ...
- vue1.0+vue2.0实现选项卡
通常我们写tab选项卡的时候,一般都是用jq等去操作dom,给同级元素移除active类,然后,给被点击元素添加active类,用vue实现也是同样的原理,都是操作active类. 我们都知道用vue ...
- 利用 Python_tkinter 完成 2048 游戏
成品展示 具备基本的数据合并以及分数统计,不同数字的色块不同 产生随机数, 数据无法合并判定以及重新开始选项 同时可以判定游戏失败条件 需求分析 完成基本数据合并算法 游戏结束条件 界面展示 重置按钮 ...
- 并发容器学习—ConcurrentSkipListMap与ConcurrentSkipListSet 原
一.ConcurrentSkipListMap并发容器 1.ConcurrentSkipListMap的底层数据结构 要学习ConcurrentSkipListMap,首先要知道什么是跳表或跳 ...