首页 > 其他分享 >AGC009B 题解

AGC009B 题解

时间:2024-08-03 13:28:28浏览次数:8  
标签:AGC009B int 题解 dfs1 战图 虚点 深度

注意到如果把每一对胜者败者连边,可以得到一颗树:

(例子)

但是因为胜者每次只能和一个败者打,所以要用类似多叉转二叉的方法,让有不止一个孩子的节点变成有一个孩子和一个虚点。

如图,原来 \(1\) 有三个儿子 \(2,3,4\),通过转换,变成了上图。

上图可以直接变成对战图(\(x2\to x1\to 1)\):

(原树不可以换根,否则构造出的对战图是错的!)

对战图深度即为树的深度。

所以这变成了求出转化后树深度最小值。

根据贪心,一定是越深的子树越靠近父节点(经过的虚点最少)。

所以应该是:

于是设 \(f_i\) 为以 \(i\) 为根的子树深度最小值。

根据上面结论,直接 dp 即可。

也就是求出儿子排列 \(p\) 使得 \(\max_{i=1}^{sz(sons)}f_{p_i}+i\) 最小。

显然 \(p\) 按照 \(f\) 为关键字排序就可以了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 1e5 + 5;

vector<int> e[N];
int n, f[N];

void dfs1(int x, int fa)
{
    vector<int> v;
    for(int i : e[x])
    {
        dfs1(i, x);
        v.push_back(f[i]);
    }
    sort(v.begin(), v.end(), greater<>());
    for(int i = 0; i < v.size(); i ++)
        f[x] = max(f[x], v[i] + i + 1);
}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    cin >> n;
    for(int i = 2; i <= n; i ++)
    {
        int x; cin >> x;
        e[x].push_back(i);
    }
    dfs1(1, 0);
    cout << f[1];

    return 0;
}

标签:AGC009B,int,题解,dfs1,战图,虚点,深度
From: https://www.cnblogs.com/adam01/p/18340351

相关文章

  • AGC049A 题解
    弱化版:CF280CGameonTree(有向图的限制变成一棵根节点为1的外向树)弱化版解法:根据期望线性性,\(Ans=\sum_{i=1}^nE(p_i)\)。其中\(p_i\)是\(i\)被选到的概率。因为对于\(i\)和\(i\)的祖先节点,某个点在这些店里是第一个备选的概率相同。所以\(p_i=\dfrac{1}{dep_i}\)......
  • joisc2017 D3T1 长途巴士 题解
    joisc2017D3T1长途巴士题解这是学校ACM欢乐赛的题,赛时想到做法了,但是因为我各种唐诗没写出来翻了转化题面我们发现,只可以踢掉检查站前面一个连续段的接水人,并且不能踢掉司机,考虑画出对整个路程表示的线段上图几个小点是检查点,考虑在每个检查点之前踢掉一段的人,容易发......
  • ABC269F 题解
    注意到第\(i\)行和第\(i+2\)行被删除的格子的排列顺序相同,格子上的数差了\(2m\)。于是处理出第\(i,i+1\)行的答案\(a_i,a_{i+1}\),有值的格子的个数\(c_i,c_{i+1}\)。令\(s(i)=\dfrac{(i-1)i}2\),也就是\(\sum_{j=1}^{i-1}j\)。第\(i,i+2,i+4\cdots\)行的和:\(a_i\t......
  • ABC268F 题解
    考虑贪心。设字符串\(S\)里数字之和为\(S_d\),X的个数为\(S_c\)。考虑相邻的两个字符串\(A,B\)的贡献:考虑临项交换,这只影响到相邻两个串的相互贡献。注意到交换\(A,B\)只会影响到\(B_dA_c,A_dB_c\),那么产生的贡献\(\Delta=B_dA_c-A_dB_c\)。因为对于最优解,\(\Delta......
  • ACM第三次测试部分题解(B,C,D,E,J)
    (B)N^N(简单快速幂模板,直接套用就行)点击查看代码#include<iostream>usingnamespacestd;longlonga,b,n;intmain(){cin>>n;while(n--){scanf("%lld",&a);signedlonglongA=a%10,sum=1;while(a)......
  • AGC039B 题解
    因为一条边只能在\(V_i,V_i+1\)之间,如果把\(V_1,V_3,\cdots\)看作一部分,\(V_2,V_4,\cdots\)看作一部分,这就是个二分图。考虑一个二分图怎么“展开”成最多的集合。考虑答案上界。上界是点对最短路的最大值加一。如果集合个数超过上界,那么一定存在一条边跨越多个集合。猜......
  • AGC033C 题解
    这里树的直径\(l\)定义为两个有硬币的点的最长距离。做一次操作后,树的直径一定会变短。我们发现,如果在直径端点做操作,直径减一。在非直径端点操作,直径减二。于是变成了一个威佐夫博弈,但是要注意的是,在直径长度为0,1,2的时候,每次都只能让直径减一。因为直径长度为1,先手必......
  • AGC059B 题解
    对于一种构造,考虑怎么表示。可以把相邻不同颜色建图连边。注意到答案不可能小于\(n-1\),否则图不联通,显然不可能。考虑什么情况下是\(n-1\)。图是一棵树。考虑怎么构造出一棵树。因为一种颜色出现次数大于等于这个点的度数,可以考虑可以确定叶子。把剩余度数最小的往最大的......
  • AGC056A 题解
    首先考虑\(n\equiv0\pmod3\)的情况。非常简单,然后考虑\(n\equiv1\pmod3\)的情况。只要把多出来的第一列第一行填满就行了。还要比原来情况多一个连通块。然后考虑\(n\equiv2\pmod3\)的情况。手玩一下,再往左上角添一点东西就行了。#include<bits/stdc++.h>us......
  • AGC044B 题解
    考虑每次更新就跑一遍bfs。\(O(n^4)\),复杂度不对?但是注意到\(dis\)的最大值也就是\(n\),每次更新\(dis\)至少减一。所以最大值最多被更新\(n\)次,一共更新\(O(n^3)\)次,复杂度是对的。直接暴力。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;......