1 条题解

  • 0
    @ 2025-8-24 22:47:44

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Poole_tea
    不明不白

    搬运于2025-08-24 22:47:44,当前版本为作者最后更新于2025-01-21 21:13:46,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    先来转化一下所给条件。

    先看第一个条件,意味着这个集合的点处在同一条链上。

    再看第二个条件,意味着这个集合处在不同的链上,处在同一深度。

    那么我们将树进行长链剖分,那么假设将长度在前 xx 的链当作第一个集合,那么后面的点要么是也是第一个集合,要么是第二个集合,而第二个集合的数量应是剩下链中的长度最大值,假设我们不按照长度一个一个选链,而是跳着选,那么这种一定不会是最优的,你可以手玩几组数据就知道了。于是我们可以进行枚举所选的链,然后再统计答案即可。

    有一个坑点,就是别拿邻接表存图,因为多测清空邻接表复杂度有点很高,会 TLE。其他就没了。

    Code

    #include <bits/stdc++.h>
    using namespace std ;
    const int MAXN = 1e6 + 10 ;
    struct edge {
        int to, nxt ;
    }e[MAXN] ;
    int head[MAXN] ;
    int len[MAXN], son[MAXN], siz[MAXN], tot ;
    inline int read() {
    	register int x = 0, f = 0;
    	register char ch = getchar();
    	while (ch < '0' || ch > '9')
    		f |= ch == '-', ch = getchar();
    	while (ch >= '0' && ch <= '9')
    		x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
    	return f ? -x : x;
    }
    inline void add (int u, int v) {
        e[++tot].to = v ;
        e[tot].nxt = head[u] ;
        head[u] = tot ;
    }
    inline bool cmp (int x, int y) {
        return x > y ;
    }
    inline void dfs (int x) {
        for (int i = head[x] ; i ; i = e[i].nxt) {
           int v = e[i].to ;
           dfs(v) ;
           if (siz[son[x]] < siz[v]) son[x] = v ;
        }
        siz[x] = siz[son[x]] + 1 ;
    }
    inline void redfs (int x, int k) {
        if (!son[x]) len[++tot] = k ;
        else redfs(son[x], k + 1) ;
        for (int i = head[x] ; i ; i = e[i].nxt) {
            int v = e[i].to ;
            if (v != son[x]) redfs (v, 1) ;
        }
    }
    int main () {
        int t ;
        t = read() ;
        while (t--) {
            int n ;
            n = read() ;
            int x ;
            for (int i = 1 ; i <= n ; i++) head[i] = 0, son[i] = 0 ;
            tot = 0 ;
            for (int i = 2 ; i <= n ; i++) {
                x = read() ;
                add(x, i) ;
            }
            tot = 0 ;
            dfs(1) ;
            redfs(1, 1) ;
            sort(len + 1, len + tot + 1, cmp) ;
            int ans = len[1] ;
            len[tot + 1] = 0 ;
            for (int i = 1 ; i <= tot ; i++) ans = min(i + len[i + 1], ans) ;
            cout << ans << '\n' ;
        }
    }
    
    • 1

    信息

    ID
    8794
    时间
    2000ms
    内存
    512MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者