• [CF1453E] Dog Snacks


    [CF1453E] Dog Snacks - 树形dp

    Description

    给定一颗n个节点的树,从一号的出发要最终回到一号点,除了一号点,每个点都只能被访问一次,要做到能走就走,现在求单次步长最大的最小值

    Solution

    基本思路是,处理完一个子树以后,再去处理另一个子树

    对每个结点,我们维护一个跳出距离,即进入这个子树后,最后退出时的最小距离,换句话说,其实就是到最近的叶子的距离

    那么对于任意一个内部分支点,它对答案的贡献,就是其所有子树中最大的跳出距离 + 1

    这里有的跳出距离充当的是在子树间横跳,有的是跳出整个子树,但无论如何,其贡献都可以这样表示

    对于叶子,贡献自然为 0

    对于根,比较特殊,由于最后不需要跳出去,所以不能按上面那样算,需要修正为,各个子树间,最大的跳出距离 和 次大的跳出距离 + 1 之间的较大值

    对于只有一个孩子的内部点,不需要统计贡献

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    const int N = 1e6 + 5;
    vector<int> g[N];
    int h[N];
    vector<int> seq;
    int ans = 0;
    
    void dfs1(int p, int from)
    {
        h[p] = 1e18;
        for (auto q : g[p])
        {
            if (q == from)
                continue;
            dfs1(q, p);
            h[p] = min(h[p], 1 + h[q]);
        }
        if (h[p] == 1e18)
            h[p] = 0;
    }
    
    void dfs2(int p, int from)
    {
        int fir = 0, sec = 0;
        for (auto q : g[p])
        {
            if (q == from)
                continue;
            dfs2(q, p);
            if (h[q] + 1 >= fir)
            {
                sec = fir;
                fir = h[q] + 1;
            }
            else
            {
                if (h[q] + 1 > sec)
                    sec = h[q] + 1;
            }
        }
        if (p != 1)
        {
            if (g[p].size() >= 3)
            {
                ans = max(ans, fir + 1);
            }
        }
        else
        {
            ans = max(ans, max(fir, sec + 1));
        }
    }
    
    void solve()
    {
        int n;
        cin >> n;
    
        for (int i = 1; i <= n; i++)
            g[i].clear();
        for (int i = 1; i <= n; i++)
            h[i] = 0;
        seq.clear();
        ans = 0;
    
        for (int i = 1; i < n; i++)
        {
            int u, v;
            cin >> u >> v;
            g[u].push_back(v);
            g[v].push_back(u);
        }
    
        dfs1(1, 0);
    
        dfs2(1, 0);
    
        cout << ans << endl;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        int t;
        cin >> t;
    
        while (t--)
        {
            solve();
        }
    }
    
  • 相关阅读:
    Extjs4 MVC Controller中refs使用
    Mac下下载android4.2源码,进行源码调试
    来博客园一年三个月
    今天写的比较多
    Extjs4 MVC 添加view层
    mac自带vim7配置
    动态测试及调试工具
    等价类划分的延伸
    用javascript进行测试用例的验证
    同行评审在软件测试中的应用
  • 原文地址:https://www.cnblogs.com/mollnn/p/14498372.html
Copyright © 2020-2023  润新知