zoukankan      html  css  js  c++  java
  • 计算机(换根dp)⭐

    题面

    一所学校前一段时间买了第一台计算机(所以这台计算机的ID是1)。

    近年来,学校又购买了N-1台新计算机。

    每台新计算机都与之前买进的计算机中的一台建立连接。

    现在请你求出第i台计算机到距离其最远的计算机的电缆长度。

    例如,上图中距离计算机1最远的是计算机4,因此 S1=3;距离计算机2最远的是计算机4和5,因此 S2=2;距离计算机3最远的是计算机5,所以 S3=3;同理,我们也得到 S4=4,S5=4。

    输入格式

    输入包含多测试数据。

    每组测试数据第一行包含整数N。

    接下来N-1行,每行包含两个整数,第 i 行的第一个整数表示第 i 台电脑买入时连接的电脑编号,第二个整数表示这次连接花费的电缆长度。

    输出格式

    每组测试数据输出N行。

    第 i 行输出第 i 台电脑的 Si。

    数据范围

    1≤N≤10000,
    电缆总长度不超过109

    输入样例:

    5
    1 1
    2 1
    3 1
    1 1
    

    输出样例:

    3
    2
    3
    4
    4
    

    题解

    标准的换根dp

    首先想到对于定根为1 f[u] = max(f[u], f[son] + cost)

    然后递归dfs, 就可以解出根为1的ans

    怎么换根呢? 也是dfs, f[son] = max(f[son], f[u] + cost)

    问题来了!

    你怎么知道f[u]不是通过f[son]得到的呢?

    这样不就套娃了? 根 根据儿子得到最大值, 儿子又通过根得到最大值

    所以自然想到 设状态为 f[u][2]

    f[u][0] = <根为u的最大值, 是通过儿子x得到的>

    f[u][1] = <根为u的次大值, 是通过儿子y得到的> (y != x, f[u][1] <= f[u][0])

    换根的时候判断一下是选 f[u][0] 还是 f[u][1] 转移就好了

    至于复杂度, 两个dfs深度相同, 每个dfs每个节点就访问为一次

    代码

    #include <bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    #define fi first
    #define se second
    using namespace std;
    typedef pair<int, int> PII;
    
    const int maxn = 10005;
    
    int n, ans[maxn];
    int h[maxn], to[maxn], ne[maxn], co[maxn], tot;
    PII f[maxn][2];
    
    void add(int u, int v, int c)
    {
        ne[++tot] = h[u]; h[u] = tot; co[tot] = c; to[tot] = v;
    }
    
    void dp(int u)
    {
        for (int i = h[u]; i; i = ne[i])
        {
            int& v = to[i]; 
            dp(v);
    
            if (f[v][0].fi + co[i] > f[u][0].fi) 
                f[u][1] = f[u][0], f[u][0] = { f[v][0].fi + co[i], v };
            else if (f[v][0].fi + co[i] > f[u][1].fi)
                f[u][1] = { f[v][0].fi + co[i], v };
        }
    }
    
    void dfs(int u, int fa, int c)
    {
        int cost = c + (f[fa][0].se == u ? f[fa][1].fi : f[fa][0].fi);
        if (cost > f[u][0].fi) f[u][0] = { cost, fa };
        else if (cost > f[u][1].fi) f[u][1] = { cost, fa };
    
        ans[u] = f[u][0].fi;
    
        for (int i = h[u]; i; i = ne[i]) dfs(to[i], u, co[i]);
    }
    
    int main()
    {
        while (cin >> n)
        {
            memset(h, 0, sizeof h); tot = 0;
            memset(f, 0, sizeof f);
    
            for (int i = 2, u, c; i <= n; ++i)
            {
                cin >> u >> c;
                add(u, i, c);
            }
    
            dp(1);
    
            dfs(1, 0, 0);
    
            rep (i, 1, n) cout << ans[i] << '
    ';
        }
        return 0;
    }
    
  • 相关阅读:
    SQL Server给一批用户分别单独发送销售数据清单
    SSRS(SQL Server 2016 Reporting Services)设置 Web 门户的品牌
    SQL Server中的游标
    SQL SERVER中查询参数为空(null)时默认查询所有的实现
    SQL Server注释快捷键
    MCSA 70-761 SQL Server 2016 练习题搬运
    SQL Server里Grouping Sets的威力【转】
    SQL Server判断表中某字段是否存在【转】
    Mac Homebrew安装使用更换国内镜像
    kubernetes常用命令
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/12879634.html
Copyright © 2011-2022 走看看