Problem Statement

     Elly has a graph with N+1 vertices, conveniently numbered from 0 to N. The graph is actually a rooted tree, with the root being the vertex with number zero.

Elly can move between the vertices of her tree by jumping from one vertex to another. Not all jumps are allowed. Elly may jump from vertex A to vertex B if and only if one of A and B is a (direct or indirect) descendant of the other.

Elly is currently standing in the root of the tree: vertex 0. She would like to make a sequence of N jumps that visits each of the other N vertices exactly once. Note that Elly is allowed to jump over previously visited vertices. For example, if A is an ancestor of B and B is an ancestor of C, Elly can jump from A to C or from C to A even if B has been already visited.

You are given the description of the tree: a vector <int> parent with N elements. For each i between 0 and N-1, inclusive, the vertex parent[i] is the parent of the vertex (i+1). If it is possible for Elly to visit each of the vertices 1 through N exactly once, return a vector <int> with N elements: the numbers of the vertices in the order in which she should visit them. If there is more than one possible answer, return the lexicographically smallest one. If there is no way to achieve her goal, return an empty vector <int> instead.

Definition

    
Class: EllysTree
Method: getMoves
Parameters: vector <int>
Returns: vector <int>
Method signature: vector <int> getMoves(vector <int> parent)
(be sure your method is public)

Limits

    
Time limit (s): 2.000
Memory limit (MB): 256

Notes

- A tree is a connected graph with N+1 vertices and N edges. A rooted tree is a tree in which one vertex is labeled as the root.
- In a rooted tree, the parent of vertex X is the first vertex on the path from X to the root. The root has no parent.
- In a rooted tree, vertex X is a descendant of vertex Y if Y lies on the path from X to the root.
- Given two equally long but different sequences of integers A and B, A is said to be lexicographically smaller than B if A contains a smaller number on the first position where they differ.

Constraints

- parent will contain between 1 and 100 elements, inclusive.
- Each element of parent will be between 0 and |parent|, inclusive, where "|parent|" denotes the number of elements in parent (i.e. N).
- It is guaranteed, that the given graph will be a valid rooted tree.

Examples

0)  
    
{9, 13, 7, 9, 8, 14, 14, 0, 6, 9, 2, 2, 5, 5, 7}
Returns: {1, 5, 2, 11, 13, 12, 8, 3, 7, 15, 14, 4, 6, 9, 10 }
The nodes Elly can jump to from node 6 are: {0, 8, 5, 14, 9, 10, 1, 4}.
1)  
    
{3, 4, 5, 0, 2}
Returns: {1, 2, 3, 4, 5 }
There are no branches in this tree, thus Elly can traverse it in any order.
2)  
    
{0, 0}
Returns: { }
The root has two children. No matter which of them Elly chooses first, she will not be able to get to the other, since the girl has to go back to the root, which is already visited.
3)  
    
{0, 6, 6, 2, 6, 1, 3, 5}
Returns: {2, 4, 1, 3, 7, 6, 5, 8 }
 

题意:给定一棵有根数,标号为0~n,你可以从根(0号点)开始,在这棵树上跳。你只能在子孙与祖先跳跃。要求跳跃n次后访问每个点各一次,并使访问序列字典序最小。

题解:

首先想到的是如何构造出一个可行的方案。我们把跳跃分为向上跳(深度减少)和向下跳 (深度增加)两种。显然,叶节点只可以通过向下跳来访问,访问后也只能向上跳。对于一个非根的非叶节点,其叶节点一定会被访问,我们可以使所有的非根的非叶节点都通过向上跳来访问。

这样,构造一个可行序列的方法就是:先从根跳到一个叶节点上,在逐渐向上跳,直到跳到一个子树没有都被访问的节点。然后再跳到其子树上的一个未被访问的叶节点(一定存在),重复操作。

这样的过程可以看做是用非叶节点去消掉其下方的叶节点,可以用DP处理。

因为答案要求字典序最小,我们可以每次枚举跳到哪个点上,再DP验证之后是否存在可行方案。注意DP时应忽略被访问过的点,对于当前位于的点要特殊考虑。

步数复杂度为n,枚举复杂度为n,DP复杂度为n,总复杂度O(n^3)。

代码:

 int a[],b[],c[],dp[],v[],dp2[],dep[],siz[],now,n;
void qq(int x,int fa)
{
dep[x]=dep[fa]+;
for(int i=c[x];i;i=b[i])qq(i,x);
}
bool gcd(int x,int y)
{
if(dep[x]>dep[y])swap(x,y);
while(dep[x]<dep[y])y=a[y];
return x!=y;
}
void ss(int x)
{
dp[x]=; dp2[x]=; siz[x]=;
for(int i=c[x];i;i=b[i])
{
ss(i); dp[x]=dp[x]+dp[i]; dp2[x]=max(dp2[x],dp2[i]); siz[x]=siz[x]+siz[i];
}
if((v[x]==)and(siz[x]==))dp[x]++; if(now==x)dp2[x]=;
if((dp[x]>)and(siz[x]!=)and((v[x]==)or(now==x)))
{
if(dp2[x]==)dp[x]=max(dp[x]-,);else dp[x]=max(dp[x]-,);
}
if((v[x]==)or(x==now))siz[x]++;
}
class EllysTree
{
public:
vector <int> getMoves(vector <int> parent)
{
//$CARETPOSITION$
vector <int> ans; n=parent.size();
for(int i=;i<n;i++)a[i+]=parent[i];
for(int i=;i<=n;i++){ b[i]=c[a[i]]; c[a[i]]=i; }
qq(,);
now=; v[]=; ss(); if(dp[]>)return ans;
for(int ii=;ii<=n;ii++)
{
for(int i=;i<=n;i++)
if(v[i]==)
{
if(gcd(now,i))continue;
int tnow=now; now=i; v[i]=; ss(); if(dp[]==){ ans.push_back(i); break; }
now=tnow; v[i]=;
}
}
return ans;
}
};

TopCoder[TCO2016 Round 1A]:EllysTree(1000)的更多相关文章

  1. [Google Codejam] Round 1A 2016 - The Last Word

    [Problem Description] Problem On the game show The Last Word, the host begins a round by showing the ...

  2. [Google Code Jam (Round 1A 2008) ] A. Minimum Scalar Product

    Problem A. Minimum Scalar Product   This contest is open for practice. You can try every problem as ...

  3. Google Code Jam Round 1A 2015 Problem B. Haircut 二分

    Problem You are waiting in a long line to get a haircut at a trendy barber shop. The shop has B barb ...

  4. 2008 Round 1A C Numbers (矩阵快速幂)

    题目描述: 请输出(3+√5)^n整数部分最后3位.如果结果不超过2位,请补足前导0. 分析: 我们最容易想到的方法肯定是直接计算这个表达式的值,但是这样的精度是不够的.朴素的算法没有办法得到答案.但 ...

  5. Google Code Jam 2008 Round 1A C Numbers(矩阵快速幂+化简方程,好题)

    Problem C. Numbers This contest is open for practice. You can try every problem as many times as you ...

  6. TopCoder[SRM513 DIV 1]:Reflections(1000)

    Problem Statement      Manao is playing a new game called Reflections. The goal of the game is trans ...

  7. Round 1A 2020 - Code Jam 2020

    Problem A. Pattern Matching 把每个字符串分成第一个之前,最后一个之后,中间的部分 三个部分 每个字符串的中间的部分可以直接拼接 前后两个部分需要判断下是否合法 #inclu ...

  8. Google Code Jam Round 1A 2015 解题报告

    题目链接:https://code.google.com/codejam/contest/4224486/ Problem A. Mushroom Monster 这题题意就是,有N个时间点,每个时间 ...

  9. TopCoder SRM 642 Div.2 1000 --二分+BFS

    题意: 给你一张图,N个点(0~N-1),m条边,国王要从0到N-1,国王携带一个值,当走到一条边权大于此值的边时,要么不走,要么提升该边的边权,提升k个单位花费k^2块钱,国王就带了B块钱,问能携带 ...

随机推荐

  1. winform程序登陆后关闭登录窗体

    用winform做程序的时候,我们一般都是在Program先启动登录窗体,然后登录成功后才创建主窗体,结果这就导致了登录窗体无法关闭 所以如果我们不在Program的程序入口先创建登录窗体的话就能完美 ...

  2. vue搭建vue-cli脚手架项目

    一.Node.js 1.介绍 Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine.Node.js是一个基于Ch ...

  3. centos7 nodejs二进制安装

    1.安装文件下载 1.下载地址:http://nodejs.cn/download/ 2.选择一个合适的版本下载 2.安装步骤 1.将安装包上传到指定位置(我习惯放到:/usr/local/appli ...

  4. sql 链接查询

    连接查询是另一种类型的多表查询.连接查询对多个表进行JOIN运算,简单地说,就是先确定一个主表作为结果集,然后,把其他表的行有选择性地“连接”在主表结果集上. 例如,我们想要选出students表的所 ...

  5. PHP FILTER_VALIDATE_EMAIL 过滤器

    定义和用法 FILTER_VALIDATE_EMAIL 过滤器把值作为 e-mail 地址来验证. Name: "validate_email" ID-number: 274 实例 ...

  6. AJAX(包括跨域)post请求封装

    function ajaxPost(dataUrl, parameter, callback, bef_callback, com_callback, err_callback) { $.ajax({ ...

  7. BZOJ 3771: Triple(FFT+容斥)

    题面 Description 我们讲一个悲伤的故事. 从前有一个贫穷的樵夫在河边砍柴. 这时候河里出现了一个水神,夺过了他的斧头,说: "这把斧头,是不是你的?" 樵夫一看:&qu ...

  8. 红黑数之原理分析及C语言实现

    目录: 1.红黑树简介(概念,特征,用途) 2.红黑树的C语言实现(树形结构,添加,旋转) 3.部分面试题() 1.红黑树简介 1.1 红黑树概念 红黑树(Red-Black Tree,简称R-B T ...

  9. 20140702 赋值构造函数的形参为什么一定用引用。string类的赋值运算函数的注意点

    1.复制构造函数为什么一定要用引用,而不是用值 类名::复制构造函数(类名&引用名) 传递引用,可以避免复制,如果一个数据相当大的化,进行复制会浪费很多时间的. 类名::复制构造函数(类名 变 ...

  10. html5本地存储(二)--- SQLList

    html5内置了2种本地数据库,一是被称为“SQLLite”,可以通过SQL语言来访问文件型SQL数据库.二是被称为“indexedDB” 的NoSQL类型的数据库 这篇主要讲SQLLite 在js中 ...