Luogu P3549 [POI 2013] MUL-Multidrink 题解
P3549 [POI 2013] MUL-Multidrink
非常 tricky 的一道题,模拟赛拼尽全力无法战胜,写篇题解记录一下。
容易理解的直接构造法。
按原题限制随便跳会破坏很多性质,几乎无法定向构造。考虑最后必须到 \(n\),每经过一个点,必须要遍历其所有子树,而从 \(1\to n\) 至少会经过之间的路径,路径上的节点可以调整为依次经过,所以考虑把 \(1\to n\) 的路径提出来,每次考虑子树内的构造,走完之后再走到路径上下一个节点。
考虑一个点的子树走到下一个点的子树,只会从这个点子树的根或一个儿子走到另一个点子树的根或一个儿子。
考虑从一个点的子树走出来,结合决策包容性,发现能从根节点节点走出来就从根节点走,否则就从根节点的儿子走出来。发现此时已经不存在决策了,对每个点记录能否到自己和自己儿子,按照优先级决策,可以直接构造。
观察每一次的操作,我们发现就是要实现对于每个节点的子树儿子进自己出或自己进儿子出的构造。考虑把这些组合成一个操作。
考虑无解的情况,以某个节点自己进儿子出为例。如果存在两棵大小大于 \(1\) 的子树,进入其中一棵子树回来的时候这个节点和对应子树的子节点都已经被访问过,无解。且在任意情况下,无论怎么遍历,无解的依旧无解。
以某个节点自己进儿子出为例。由上述分析有解时每个点只会有一个大小大于 \(1\) 的子树,大小为 \(1\) 的子树可以在儿子进自己出地访问完这棵子树后顺次访问,自己进儿子出访问显然无解。于是归约为了更小的问题,递归构造。时间复杂度 \(O(n)\)。
#include <bits/stdc++.h>
using namespace std;
struct edge
{
int v,nxt;
}e[4000001];
int n,u,v,h[2000001],fa[2000001],siz[2000001],ans[2000001],st[2000001],tol=0,mx=0,cnt=0,top=0;
bool vis[2000001];
void cstr_sf(int,int);
void cstr_fs(int,int);
void add_edge(int u,int v)
{
e[++cnt].nxt=h[u];
e[cnt].v=v;
h[u]=cnt;
}
void end()
{
printf("BRAK\n");
exit(0);
}
void cstr_sf(int x,int pr)
{
vector<int>ss,sl;
for(int i=h[x];i;i=e[i].nxt)
if(e[i].v!=pr&&!vis[e[i].v]&&siz[e[i].v]==1)ss.push_back(e[i].v);
else if(e[i].v!=pr&&!vis[e[i].v])sl.push_back(e[i].v);
if(sl.size()>=2)end();
for(int i=0;i<ss.size();i++)ans[++tol]=ss[i];
for(int i=0;i<sl.size();i++)cstr_fs(sl[i],x);
ans[++tol]=x;
}
void cstr_fs(int x,int pr)
{
ans[++tol]=x;
vector<int>ss,sl;
for(int i=h[x];i;i=e[i].nxt)
if(e[i].v!=pr&&!vis[e[i].v]&&siz[e[i].v]==1)ss.push_back(e[i].v);
else if(e[i].v!=pr&&!vis[e[i].v])sl.push_back(e[i].v);
if(sl.size()>=2)end();
for(int i=0;i<sl.size();i++)cstr_sf(sl[i],x);
for(int i=0;i<ss.size();i++)ans[++tol]=ss[i];
}
void dfs(int x,int pr)
{
siz[x]=1,fa[x]=pr;
for(int i=h[x];i;i=e[i].nxt)
if(e[i].v!=pr)dfs(e[i].v,x),siz[x]+=siz[e[i].v];
}
bool cstr(int x,int pr,bool flag)
{
vector<int>ss,sl;
for(int i=h[x];i;i=e[i].nxt)
if(e[i].v!=pr&&!vis[e[i].v]&&siz[e[i].v]==1)ss.push_back(e[i].v);
else if(e[i].v!=pr&&!vis[e[i].v])sl.push_back(e[i].v);
if(x==n)
{
if(siz[x]==1)ans[++tol]=x;
else
{
if(!flag)end();
cstr_sf(x,pr);
}
return 0;
}
bool tf=0;
if(ss.empty()&&sl.empty())ans[++tol]=x,tf=1;
else if(!flag)
{
if(sl.size()>=2)end();
ans[++tol]=x,tf=0;
for(int i=0;i<sl.size();i++)cstr_sf(sl[i],x);
for(int i=0;i<ss.size();i++)ans[++tol]=ss[i];
}
else
{
if(sl.size()==0)
{
for(int i=0;i<ss.size();i++)ans[++tol]=ss[i];
ans[++tol]=x,tf=1;
}
else if(sl.size()==1)
{
for(int i=0;i<ss.size();i++)ans[++tol]=ss[i];
for(int i=0;i<sl.size();i++)cstr_fs(sl[i],x);
ans[++tol]=x,tf=1;
}
else if(sl.size()==2)
{
cstr_fs(sl[0],x),ans[++tol]=x,tf=0,cstr_sf(sl[1],x);
for(int i=0;i<ss.size();i++)ans[++tol]=ss[i];
}
else end();
}
return tf;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n-1;i++)scanf("%d%d",&u,&v),add_edge(u,v),add_edge(v,u);
dfs(1,0);
int x=n;
while(x)vis[x]=1,st[++top]=x,x=fa[x];
bool tf=0;
for(int i=top;i>=1;i--)tf=cstr(st[i],0,tf);
for(int i=1;i<=tol;i++)printf("%d\n",ans[i]);
return 0;
}
Luogu P3549 [POI 2013] MUL-Multidrink 题解的更多相关文章
- Luogu 1979 NOIP 2013 华容道(搜索,最短路径)
Luogu 1979 NOIP 2013 华容道(搜索,最短路径) Description 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面 ...
- [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)
[BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...
- Moscow Subregional 2013. 部分题题解 (6/12)
Moscow Subregional 2013. 比赛连接 http://opentrains.snarknews.info/~ejudge/team.cgi?contest_id=006570 总叙 ...
- luogu NOIp热身赛(2018-11-07)题解
为什么前面的人都跑得那么快啊? QAQ T1:区间方差 题目大意:询问区间方差,支持单点修改 首先把方差的式子展开,得到 $$d = \frac{a_1 + ... a_n}{n} - \frac{a ...
- 【luogu P1955 [NOI2015]程序自动分析】 题解
题目链接:https://www.luogu.org/problemnew/show/P1955 并查集操作,1e9要离散化,数组要开大一些,操作前先执行合并操作 样例好毒啊(全是排好序的) #inc ...
- 【luogu P2195 HXY造公园】 题解
题目链接:https://www.luogu.org/problemnew/show/P2195 fir.吐槽题目(省略1w字 sec.考虑对一个森林的维护,每棵树用并查集维护. 操作1:输出当前查询 ...
- 【luogu P1073 最优贸易】 题解
题目链接:https://www.luogu.org/problemnew/show/P1073 对于状态量相互影响的题目,分层图是个不错的想法. 考虑在题目中分为: 不交易: 直接从1到n出去,为0 ...
- 【luogu P3393 逃离僵尸岛】 题解
题目链接:https://www.luogu.org/problemnew/show/P3393 被占领的点可以先连在一个点上然后只需要对这一个点bfs一遍就可以求所有的危险点 #include &l ...
- 【luogu P4017 最大食物链计数】 题解
题目链接:https://www.luogu.org/problemnew/show/P4017 DAG + DP #include <queue> #include <cstdio ...
- 【luogu P1351 联合权值】 题解
题目链接:https://www.luogu.org/problemnew/show/P1351 做了些提高组的题,不得不说虽然NOIP考察的知识点虽然基本上都学过,但是做起题来还是需要动脑子的. 题 ...
随机推荐
- MaxKB web 站点知识库选择器的花样玩法
背景:MaxKB 创建知识库支持"web 站点"的这种形式,但是很多同学不知道怎么录入选择器来针对性的获取某一部分内容. 1. 选择器作用 选择器用于定位网页中特定的元素,以便获取 ...
- TortoiseGit安装(Windows10环境)
1.前往官网下载 https://tortoisegit.org/download/ 根据自己系统位数进行选择 2.双击运行 3.默认即可,第一个是基于PuTTY的SSH客户端,与Windows兼容更 ...
- web自动化的元素定位
一.基础元素定位 1.id定位:根据元素的id定位 By.id("id") webDriver.findElement(By.id("tab-account") ...
- 智能语音备忘录:SpeechRecognition与gTTS的奇妙融合
引言:智能语音备忘录的时代已经到来 在这个信息爆炸的时代,我们每天需要处理大量的事务和信息.传统的文字记录方式虽然可靠,但在效率上往往难以满足快节奏生活的需求.想象一下,如果你能在驾车.散步或是灵感突 ...
- 【记录】Prompt模板|作为甲方怎么清晰专业地描述自己的需求(又名“乙方,给你的甲方扔个GPT解放自己吧”)
这篇Prompt摘抄并修改自朋友送给我的书的第49页5.2.3让ChatGPT构建提示,质量挺不错,支持一下她的博客:[好书推荐2]AI提示工程实战:从零开始利用提示工程学习应用大语言模型. 书长这样 ...
- ChatGPT为何放弃WebSocket?揭秘EventSource的三大决胜优势
ChatGPT为何放弃WebSocket?揭秘EventSource的三大决胜优势 感觉本篇对你有帮助可以关注一下我的微信公众号(深入浅出谈java),会不定期更新知识和面试资料.技巧!!! Chat ...
- CentOS 7.6安装nginx
1.安装EPEL仓库 [root@ecs-lanxinmeichen nginx]# sudo yum install epel-releaseLoaded plugins: fastestmirro ...
- 告别安装烦恼!Linux下MySQL一站式部署宝典
前言 本次安装部署主要针对Linux环境进行安装部署操作,系统位数64 getconf LONG_BIT 64 MySQL版本: v5.7.38 一.下载MySQL MySQL下载地址:https:/ ...
- Longest Substring Without Repeating Characters---LeetCode进阶路③
题目描述 Given a string, find the length of the longest substring without repeating characters. Example ...
- HarmonyOS NEXT开发教程:全局悬浮窗
今天跟大家分享一下HarmonyOS开发中的悬浮窗. 对于悬浮窗,可能有的同学会想到使用层叠布局是否可以实现,将悬浮窗叠在导航栏组件Tabs上,像这样: Stack({alignContent:Ali ...