#P13642. EERT

EERT

题目背景

顺着走是不可能的!这辈子都不可能!

题目描述

本题仅允许使用 C++ 语言提交。

小 S 有一颗有 NN 个节点的树,现在他邀请小 T 参观这棵树的每一个节点。

因为顺着走太无聊,所以小 S 想找到一个参观顺序,使得没有相邻两个参观的点在树上是相连的,并且每个节点恰好参观一次。

你是小 S 雇佣的导游,所以这个问题就抛给了你。

当然,如果没有解决办法,那就说明小 S 不想带小 T 参观,你也就不用管了。

形式化的讲,给定一颗 NN 个节点的树,你需要找到一条这棵树的补图的哈密顿路径。

实现细节

在本题中,你不需要,也不能实现 main 函数和从标准输入输出流中输入输出。

本题中所有数组下标均从 00 开始。

你需要实现下面一个函数:

std::vector<int> eert(int N,std::vector<int> f)
  • 本题保证每个测试点仅会调用 11 次该函数。
  • NN 是这个树的节点个数,保证 1N1071\leq N\leq 10^7
  • 树上点的编号从 11NN
  • ff 是一个长度为 N1N-1 的数组,其中 fif_i 表示点 i+2i+2 和点 fif_i 之间有条边,保证 1fii+11\leq f_i \leq i+1
  • 你需要返回一个大小为 NN 或者为 00 的数组(vector)。具体的:如果有解,返回一个长度为 NN 的数组,表示你的答案;如果无解,返回一个空的数组。
  • 你返回的数组设为 ansans,你需要保证 ansans 是一个 1N1-N 的排列,下标从 00 开始,且对于 1i<N1\leq i<Nansi1ans_{i-1}ansians_i 之间没有连边。

输入格式

第一行一个整数 NN,表示树的大小。

第二行 N1N-1 个整数,表示数组 ff

输出格式

输出一行,表示交互结果,有以下几种情况:

  1. No 表示你的函数返回无解;
  2. Wrong answer 表示你的函数返回了错误的哈密顿路径(包括不合法的返回);
  3. Yes 表示你的函数找到了正确的哈密顿路径。

其中,2,32,3 会同时输出你的函数返回的排列。

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 #001010pts):N10N\leq10
  • 对于 Subtask #111515pts):N20N\leq20
  • 对于 Subtask #2255pts):保证 fi=1f_i=1
  • 对于 Subtask #331010pts):保证 fi=i+1f_i=i+1
  • 对于 Subtask #442020pts):保证 N105N\leq10^5
  • 对于 Subtask #554040pts):无特殊限制。

对于 100%100\% 的数据:1N107,1fii+11\leq N\leq10^7,1\leq f_i\leq i+1

本题 SPJ 需要使用不超过 200200MB 的内存和 300300ms 的时间,这是无法避免的,请注意你的空间和时间,与交互库相加不能超过对应的限制。