zoukankan      html  css  js  c++  java
  • [换根DP]luogu P3647 [APIO2014]连珠线

    题面

    https://www.luogu.com.cn/problem/P3647

    不重复地取树中相邻的两条边,每次得分为两条边权和,问最大得分

    分析

    容易想到状态 f[i][0/1] 分别表示 i 号点不作为/作为两条边的经过点的以 i 为根子树中的最大得分

    显然有 $f[i][0]=/sum max(f[j][0],f[j][1]+w_{i,j})$

    又因为显然只可能有一对相邻边穿过 i ,转移时减去 f[i][0] 中 j 的贡献再加上连接 i,j 的贡献即可

    $f[i][1]=f[i][0]-max{f[j][0]+w_{i,j}-max(f[j][0],f[j][1]+w_{i,j}}$

    换根也很容易, f[i][0] 的转移是简单加法,所以减去加上贡献即可

    f[i][1]的转移包含了最大值,套路记录次大值即可,注意转移时父亲的贡献

    代码

    #include <iostream>
    #include <cstdio>
    using namespace std;
    const int Inf=2147483647;
    const int N=2e5+10;
    struct Graph {
        int v,w,nx;
    }g[2*N];
    int cnt,list[N];
    int n,ans,f[N][2],mx[N][2];
    
    void Add(int u,int v,int w) {g[++cnt]=(Graph){v,w,list[u]};list[u]=cnt;}
    
    void DFS(int u,int fa) {
        mx[u][0]=mx[u][1]=f[u][1]=-Inf;
        for (int i=list[u],val;i;i=g[i].nx)
            if (g[i].v!=fa) {
                DFS(g[i].v,u);
                f[u][0]+=max(f[g[i].v][0],f[g[i].v][1]+g[i].w);
                val=f[g[i].v][0]+g[i].w-max(f[g[i].v][0],f[g[i].v][1]+g[i].w);
                if (mx[u][0]<val) mx[u][1]=mx[u][0],mx[u][0]=val;
                else mx[u][1]=max(mx[u][1],val);
            }
        f[u][1]=f[u][0]+mx[u][0];
    }
    
    void DFS(int u,int fa,int faw) {
        if (fa) f[u][0]+=max(f[fa][0],f[fa][1]+faw);
        ans=max(ans,f[u][0]);
        for (int i=list[u],a,b;i;i=g[i].nx)
            if (g[i].v!=fa) {
                a=f[u][0];b=f[u][1];
                f[u][0]-=max(f[g[i].v][0],f[g[i].v][1]+g[i].w);
                f[u][1]=f[u][0]+((mx[u][0]==f[g[i].v][0]+g[i].w-max(f[g[i].v][0],f[g[i].v][1]+g[i].w))?mx[u][1]:mx[u][0]);
                if (fa) f[u][1]=max(f[u][1],f[u][0]+f[fa][0]+faw-max(f[fa][0],f[fa][1]+faw));
                DFS(g[i].v,u,g[i].w);
                f[u][0]=a;f[u][1]=b;
            }
    }
    
    int main() {
        scanf("%d",&n);
        for (int i=1,u,v,w;i<n;i++) scanf("%d%d%d",&u,&v,&w),Add(u,v,w),Add(v,u,w);
        DFS(1,0);DFS(1,0,0);printf("%d
    ",ans);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    Number Sequence ----HDOJ 1711
    B. Berland Bingo
    迷宫城堡--HDOJ 1269(Tarjan)
    迷宫城堡--HDOJ 1269
    前向星,链式前向星
    linux下建立无线wifi------简单实用!
    leetcode187- Repeated DNA Sequences- medium
    leetcode173- Binary Search Tree Iterator- medium
    leetcode170- Two Sum III
    leetcode167- Two Sum II
  • 原文地址:https://www.cnblogs.com/mastervan/p/14577030.html
Copyright © 2011-2022 走看看