• bzoj3743【题解】Kamp


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743

    这道题第一想法是暴力。

    但是没有细分数据点。

    硬想了半天没有思路。

    只好去搜题解。但是题解看着好麻烦的。

    于是就综合了很多题解的思路。

    选择用两次树形DP

    第一次先求一些必要的值。

    把第一个关键点设为根。从它开始DP。

    第二次也是一样,以第一个为根,更新答案。

    细节可以看注释。

    如下。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=500005;
    int n,k,tot,head[maxn],d[maxn];
    bool have[maxn<<1];
    struct node{
        int nxt,dis,to;
        #define nxt(x) e[x].nxt
        #define dis(x) e[x].dis
        #define to(x) e[x].to
    }e[maxn<<1];
    inline void add(int from,int to,int v){
        to(++tot)=to;dis(tot)=v;
        nxt(tot)=head[from];head[from]=tot;
    }
    int num[maxn];//以它为根的子树中有多少关键点。
    ll f[2][maxn],val[maxn];//f[0][x]表示从x向下走到下一个关键点的最大长,f[1][x]是次大
    inline void doo1(int now,int fa){
        num[now]=have[now];
        for(int i=head[now];i;i=nxt(i)){
            int t=to(i);
            if(t==fa) continue;
            doo1(t,now);
            if(!num[t]) continue;
            num[now]+=num[t];
            val[now]+=val[t]+dis(i);
            int tmp=f[0][t]+dis(i);
            if(tmp>f[0][now]){ 
                f[1][now]=f[0][now];
                f[0][now]=tmp;
            }else if(tmp>f[1][now])
                    f[1][now]=tmp;
        }
    }
    ll ans[maxn];//答案
    inline void push(int now,int fa){
        for(int i=head[now];i;i=nxt(i)){
            int t=to(i);
            if(t==fa) continue;
            ans[t]=ans[now]+dis(i);
            push(t,now);
        }
    }
    //up表示now到上一个关键点的距离
    inline void doo2(int now,int fa,ll up,ll sum){
        ans[now]=2*sum-max(up,f[0][now]);//更新答案,画图可以得到
        for(int i=head[now];i;i=nxt(i)){
            int t=to(i);
            if(t==fa) continue;
            if(num[t]){//如果to是关键点求up
                ll tmp=0;
                if(up||have[now]) tmp=max(tmp,up+dis(i));
                if(f[0][now]==f[0][t]+dis(i)){
                    if(f[1][now])
                        tmp=max(tmp,f[1][now]+dis(i));
                }else
                    tmp=max(tmp,f[0][now]+dis(i));
                doo2(t,now,tmp,sum);
            }else{//直接求然后下放
                ans[t]=ans[now]+dis(i);
                push(t,now);
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n-1;i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);add(y,x,z);
        }
        for(int i=1;i<=k;i++)
            scanf("%d",&d[i]),have[d[i]]=1;
        doo1(d[1],0);
        doo2(d[1],0,0,val[d[1]]);
        for(int i=1;i<=n;i++)
            printf("%lld
    ",ans[i]);
        system("pause");
        return 0;
    }
  • 相关阅读:
    修改tomcat的get方法的参数长度
    [转]修改hosts文件不起作用
    [转]solr DataImportHandler 解决mysql 表导入内存溢出问题
    plat模板修改记录
    Linux基本命令
    使用DTM ( Dynamic Topic Models )进行主题演化实验
    Stuts2的"struts.devMode"设置成true后,不起作用,仍需要重启tomcat
    R语言——绘图函数深入学习
    R语言——基本绘图函数
    Stem Cell 华人科学家
  • 原文地址:https://www.cnblogs.com/ChrisKKK/p/11262826.html
Copyright © 2020-2023  润新知