• #4703. 旅行


    题目描述

    题解

    考虑暴力以每个点为根,如果要回到这个点的话那就是到k个点的不重路径的总和的两倍,所以再减去最远点的路径长即可,dp即可

    考虑正解,发现可以换根,于是 $O(n)$ 即可

    代码

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int N=5e5+5,M=N<<1;
    int n,k,t,sz[N],fl[N],hd[N],V[M],W[M],nx[M];
    LL f[N],g[N],ans[N];
    void add(int u,int v,int w){
        nx[++t]=hd[u];V[hd[u]=t]=v;W[t]=w;
    }
    void dfs(int x,int fr){
        sz[x]=fl[x];f[x]=g[x]=0;
        for (int i=hd[x];i;i=nx[i])
            if (V[i]!=fr){
                dfs(V[i],x);sz[x]+=sz[V[i]];
                if (sz[V[i]])
                    f[x]+=f[V[i]]+2ll*W[i],
                    g[x]=max(g[x],g[V[i]]+W[i]);
            }
    }
    void dp(int x,int fr,int w){
        ans[x]=f[x]-g[x];
        LL ax1=0,ax2=0;int id=0;
        for (int i=hd[x];i;i=nx[i])
            if (V[i]!=fr && sz[V[i]]){
                if (ax1<g[V[i]]+W[i])
                    ax2=ax1,ax1=g[V[i]]+W[i],id=V[i];
                else ax2=max(ax2,g[V[i]]+W[i]);
            }
        if (sz[fr]){
            if (ax1<g[fr]+w)
                ax2=ax1,ax1=g[fr]+w,id=fr;
            else ax2=max(ax2,g[fr]+w);
        }
        for (int i=hd[x];i;i=nx[i])
            if (V[i]!=fr){
                if (sz[V[i]]){
                    f[x]-=f[V[i]]+2ll*W[i];
                    if (id==V[i]) g[x]=ax2;
                    f[V[i]]+=f[x]+2ll*W[i];
                    g[V[i]]=max(g[V[i]],g[x]+W[i]);
                }
                else f[V[i]]=f[x]+2ll*W[i],g[V[i]]=g[x]+W[i];
                sz[x]-=sz[V[i]];sz[V[i]]+=sz[x];dp(V[i],x,W[i]);
                sz[V[i]]-=sz[x];sz[x]+=sz[V[i]];
                if (sz[V[i]]){
                    f[V[i]]-=f[x]+2ll*W[i];
                    f[x]+=f[V[i]]+2ll*W[i];g[x]=ax1;
                }
            }
    }
    int main(){
        scanf("%d%d",&n,&k);
        for (int x,y,z,i=1;i<n;i++)
            scanf("%d%d%d",&x,&y,&z),
            add(x,y,z),add(y,x,z);
        for (int x,i=1;i<=k;i++)
            scanf("%d",&x),fl[x]=1;
        dfs(1,0),dp(1,0,0);
        for (int i=1;i<=n;i++)
            printf("%lld
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    周练2
    周练1
    周赛6(28)
    django中的orm:
    crm项目包含django创建虚拟环境:
    crm项目建表(django自带认证、分页、插件功能):
    自动化测试js代码打印类名:
    pages框架之豆瓣:
    mybatis反向生成实体类、dao层以及映射文件
    mybatis反向生成实体类、dao层以及映射文件
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12263379.html
Copyright © 2020-2023  润新知