#P13642. EERT
EERT
题目背景
顺着走是不可能的!这辈子都不可能!
题目描述
本题仅允许使用 C++ 语言提交。
小 S 有一颗有 个节点的树,现在他邀请小 T 参观这棵树的每一个节点。
因为顺着走太无聊,所以小 S 想找到一个参观顺序,使得没有相邻两个参观的点在树上是相连的,并且每个节点恰好参观一次。
你是小 S 雇佣的导游,所以这个问题就抛给了你。
当然,如果没有解决办法,那就说明小 S 不想带小 T 参观,你也就不用管了。
形式化的讲,给定一颗 个节点的树,你需要找到一条这棵树的补图的哈密顿路径。
实现细节
在本题中,你不需要,也不能实现 main 函数和从标准输入输出流中输入输出。
本题中所有数组下标均从 开始。
你需要实现下面一个函数:
std::vector<int> eert(int N,std::vector<int> f)
- 本题保证每个测试点仅会调用 次该函数。
- 是这个树的节点个数,保证 。
- 树上点的编号从 到 。
- 是一个长度为 的数组,其中 表示点 和点 之间有条边,保证 。
- 你需要返回一个大小为 或者为 的数组(
vector
)。具体的:如果有解,返回一个长度为 的数组,表示你的答案;如果无解,返回一个空的数组。 - 你返回的数组设为 ,你需要保证 是一个 的排列,下标从 开始,且对于 , 与 之间没有连边。
输入格式
第一行一个整数 ,表示树的大小。
第二行 个整数,表示数组 。
输出格式
输出一行,表示交互结果,有以下几种情况:
No
表示你的函数返回无解;Wrong answer
表示你的函数返回了错误的哈密顿路径(包括不合法的返回);Yes
表示你的函数找到了正确的哈密顿路径。
其中, 会同时输出你的函数返回的排列。
5
1 1 1 1
No
7
1 1 2 2 3 3
Yes
1 4 5 6 7 2 3
提示
本地测试
你可以在代码末尾加入如下代码测试(提交时请删去或注释掉)。
#include<bits/stdc++.h>
using namespace std;
namespace CHECKER{
int N;
vector<int> f;
vector<int> ans;
vector<int> vis;
bool checker(){
if(ans.size()!=N) return 0;
for(int i=0;i<N;i++) if(ans[i]<=0||N<ans[i]) return 0;
vis.resize(N,0);
for(int i=0;i<N;i++){
if(vis[ans[i]-1]) return 0;
vis[ans[i]-1]=1;
}
int u,v;
for(int i=1;i<N;i++){
u=ans[i-1];
v=ans[i];
if(u!=1&&f[u-2]==v||v!=1&&f[v-2]==u) return 0;
}
return 1;
}
int main(){
scanf("%d",&N);
f.resize(N-1);
for(int i=0;i<N-1;i++){
scanf("%d",&f[i]);
}
ans=eert(N,f);
if(ans.empty()){
printf("NO\n");
return 0;
}
if(checker()) printf("YES\n");
else printf("Wrong answer\n");
for(int i=0;i<ans.size();i++){
printf("%d ",ans[i]);
}
printf("\n");
return 0;
}
}
int main(){
return CHECKER::main();
}
其中,输入输出格式为题面中的【输入格式】和【输出格式】。
本题有捆绑测试。
- 对于 Subtask #(pts):
- 对于 Subtask #(pts):
- 对于 Subtask #(pts):保证 。
- 对于 Subtask #(pts):保证 。
- 对于 Subtask #(pts):保证 。
- 对于 Subtask #(pts):无特殊限制。
对于 的数据:。
本题 SPJ 需要使用不超过 MB 的内存和 ms 的时间,这是无法避免的,请注意你的空间和时间,与交互库相加不能超过对应的限制。