zoukankan      html  css  js  c++  java
  • UPC-5622 Tournament(树的最小深度构造)

    题目描述
    N contestants participated in a competition. The total of N−1 matches were played in a knockout tournament. For some reasons, the tournament may not be “fair” for all the contestants. That is, the number of the matches that must be played in order to win the championship may be different for each contestant. The structure of the tournament is formally described at the end of this statement.

    After each match, there were always one winner and one loser. The last contestant standing was declared the champion.
    这里写图片描述

    For convenience, the contestants were numbered 1 through N. The contestant numbered 1 was the champion, and the contestant numbered i(2≤i≤N) was defeated in a match against the contestant numbered ai.

    We will define the depth of the tournament as the maximum number of the matches that must be played in order to win the championship over all the contestants.

    Find the minimum possible depth of the tournament.

    The formal description of the structure of the tournament is as follows. In the i-th match, one of the following played against each other:

    Two predetermined contestants
    One predetermined contestant and the winner of the j-th match, where j(j < i) was predetermined
    The winner of the j-th match and the winner of the k-th match, where j and k (j,k < i,j≠k) were predetermined
    Such structure is valid structure of the tournament, if and only if no contestant who has already been defeated in a match will never play in a match, regardless of the outcome of the matches.

    Constraints
    2≤N≤105
    1 ≤ ai ≤ N (2 ≤ i ≤ N)
    It is guaranteed that the input is consistent (that is, there exists at least one tournament that matches the given information).
    输入
    The input is given from Standard Input in the following format:

    N
    a2
    :
    aN
    输出
    Print the minimum possible depth of the tournament.
    样例输入
    5
    1
    1
    2
    4
    样例输出
    3
    提示
    The following tournament and the result of the matches are consistent with the given information:

    In the first match, contestants 4 and 5 played against each other, and contestant 4 won.
    In the second match, contestants 2 and 4 played against each other, and contestant 2 won.
    In the third match, contestants 1 and 3 played against each other, and contestant 1 won.
    In the fourth match, contestants 1 and 2 played against each other, and contestant 1 won.

    The depth of this tournament is 3, since contestant 5 must play three matches in order to win the championship. There is no tournament with depth 2 or less that is consistent with the given information, thus the output should be 3.

    题意:有N个人比赛,两两进行淘汰赛,其中1将会得到比赛的最终胜利,剩余的2到N个人标号为2到N,每个人都会被ai所打败,如2被1打败,3被1打败,4被2打败,5被4打败。

    给出所有人是被谁打败的,求这样一棵淘汰赛形成的树的最小深度。

    首先根据给出的关系建树。我们要求最小的总深度,那么在保证其被规定的人打败的基础上,尽量将深度在子树中分摊开来,使子树深度较小的排在深度较深的位置,子树较深的排在较浅的位置。

    具体,举例,如1打败了2个人,2和3,那么1必定战胜了2人,这两人是有先后顺序的,因为2还战胜了其他人,所以若1先打败2再去打3,那么深度将是2的深度加上1的深度,因为1有两个子节点,那么1所形成的树必定为
    这里写图片描述

    由此看出,1因为打败2人,有两个子节点,那么关于1的子树深度必定为其子节点个数的值。
    对于2节点,我们发现其打败了4,4又打败了5,得知,2节点延展下去的子树深度为2,那么我们本着总深度最小的原则,在何处让1和2相比赛呢。当然是靠右侧较小深度的位置,而3的深度为1,没有子树,直接将其放在较深的位置,就不会增加树的总深度。

    具体实现,首先根据输入建树,父节点即ai,子节点为标号,表示标号i被ai打败。然后对树进行深搜,直到叶子节点,返回深度0,接着,在倒数第二层我们收到一个子树,dfs返回值为该子树的直接节点的最大深度。对于一个子树的所有节点返回的深度,我们对其进行从小到大的排序,目的是优先对深度较小的子树进行排列,排到该节点深的位置。首先若我们有N个子节点,那么该子树必定有至少N的深度。并且从1到N每层都有一个可以放置子节点的深度。

    对于一个深度,计算结点数(该节点最小深度)- 某子节点的排序后位置,也就是排列在哪个深度。我们可以得到一个在一定深度基础上增加子树深度的总深度,这个总深度临时记录,作为最大深度的一个候选,我们要计算总深度,即最大深度,使得最大深度最后最小。当便利完该子树的所有子节点,即可筛选出该子树的总深度,返回该子树的总深度,继续给上层树做总深度的排列和筛选。

    #include<bits/stdc++.h>
    using namespace std;
    vector<int>son[100005];
    int n,tmp;
    int dfs(int i)
    {
        if(son[i].size()==0)return 0;
        vector<int>pri;
        for(int j=0; j<son[i].size(); j++)///得到该节点所有的子节点,对于每个子节点,深度都是自己的子树
            pri.push_back(dfs(son[i][j]));
        int maxn=1;
        sort(pri.begin(),pri.end());
        for(int j=0; j<pri.size(); j++)///子节点中深度找出深度最深的,作为总深度返回
        {
            if(pri[j]+pri.size()-j>maxn)
                maxn=pri[j]-j+pri.size();///size表示该层要赢得比赛所要走的最小深度,在此基础上均摊使得深度最小,然后返回值为最大深度,最大深度为当前结点的最小深度加上均摊后的子树最大深度
        }///位序j表示从小到大的深度,说明这些结点在何时与i结点对战使总深度会最小,尽量均摊,使子树高深度的上移,也就是使得j较小的时候接上较大的深度子树
        return maxn;
    }
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            for(int i=0; i<=n; i++)
                son[i].clear();
            for(int i=2; i<=n; i++)
            {
                scanf("%d",&tmp);
                son[tmp].push_back(i);
            }
            printf("%d
    ",dfs(1));
        }
    }
    
  • 相关阅读:
    Angular项目中引入jQuery
    ERROR in Error: ***Module is not an NgModule
    angular-cli项目报Error encountered resolving symbol values statically. Function calls are not supported.错误的处理。
    在angular项目中使用bootstrap的tooltip插件时,报错Property 'tooltip' does no t exist on type 'JQuery<HTMLElement>的解决方法和过程
    微信小程序学习笔记(四)--框架-视图层
    js打印窗口内容并当窗口内容较长时自动分页
    微信小程序学习笔记(三)--框架-逻辑层
    微信小程序学习笔记(二)--框架-全局及页面配置
    微信小程序学习笔记(一)--创建微信小程序
    在ag-grid表格上实现类似Excel中的按下enter键自动跳转到下一行对应的输入框功能,Angular4开发
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135789.html
Copyright © 2011-2022 走看看