zoukankan      html  css  js  c++  java
  • uoj#11. 【UTR #1】ydc的大树

    http://uoj.ac/problem/11

    树形dp求出每个点的到最远黑点的距离 和 这个点到所有最远黑点的路径的交 的另一端(lca也可以顺便记录),然后树上差分标记一下,统计出每个点被路径交覆盖了几次,由此可以计算答案。

    #include<bits/stdc++.h>
    char ib[10000007],*ip=ib;
    int _(){
        int x=0;
        while(*ip<48)++ip;
        while(*ip>47)x=x*10+*ip++-48;
        return x;
    }
    typedef long long i64;
    const int N=1e5+7;
    const i64 inf=1ll<<60;
    struct edge{
        int to,nx,v;
    }e[N*2];
    int n,m,e0[N],ep=2,ans=-1,at,fa[N],t[N];
    bool is[N];
    struct D1{
        i64 md;
        int w;
        void upd(const D1&d,int w0){
            if(d.md>md)*this=d;
            else if(d.md==md)w=w0;
        }
        D1 operator+(int x){
            return (D1){md+x,w};
        }
    }v1[N],v2[N],D1_nul=(D1){-inf,0};
    struct D2{
        i64 md;
        int w,lca;
        void upd(const D1&d,int w0){
            if(d.md>md)md=d.md,w=d.w,lca=w0;
            else if(d.md==md)w=lca=w0;
        }
        void ins(int w0){
            ++t[w0];
            ++t[w];
            --t[lca];
            --t[fa[lca]];
        }
    }d2[N],D2_nul=(D2){-inf,0,0};
    void f1(int w,int pa){
        fa[w]=pa;
        v1[w]=is[w]?(D1){0,w}:D1_nul;
        for(int i=e0[w];i;i=e[i].nx){
            int u=e[i].to;
            if(u==pa)continue;
            f1(u,w);
            v1[w].upd(v1[u]+e[i].v,w);
        }
    }
    int cs[N],cp=0;
    void f2(int w){
        cp=0;
        for(int i=e0[w];i;i=e[i].nx){
            int u=e[i].to;
            if(u!=fa[w])cs[++cp]=i;
        }
        v2[cp+1]=D1_nul;
        for(int t=cp;t;--t){
            int i=cs[t],u=e[i].to;
            v2[t]=v2[t+1];
            v2[t].upd(v1[u]+e[i].v,w);
        }
        D1 v3=is[w]?(D1){0,w}:D1_nul;
        for(int t=1;t<=cp;++t){
            int i=cs[t],u=e[i].to;
            d2[u]=d2[w];
            d2[u].upd(v2[t+1],w);
            d2[u].upd(v3,w);
            d2[u].md+=e[i].v;
            v3.upd(v1[u]+e[i].v,w);
        }
        for(int i=e0[w],t=1;i;i=e[i].nx){
            int u=e[i].to;
            if(u!=fa[w])f2(u);
        }
        if(is[w]){
            d2[w].upd(v1[w],w);
            d2[w].ins(w);
        }
    }
    void f3(int w){
        for(int i=e0[w];i;i=e[i].nx){
            int u=e[i].to;
            if(u==fa[w])continue;
            f3(u);
            t[w]+=t[u];
        }
        if(!is[w]){
            if(t[w]>ans)ans=t[w],at=0;
            if(t[w]==ans)++at;
        }
    }
    int main(){
        fread(ib,1,sizeof(ib),stdin);
        n=_(),m=_();
        int rt=n;
        for(int i=1;i<=m;++i)is[_()]=1;
        for(int i=1,a,b,c;i<n;++i){
            a=_(),b=_(),c=_();
            e[ep]=(edge){b,e0[a],c};e0[a]=ep++;
            e[ep]=(edge){a,e0[b],c};e0[b]=ep++;
        }
        f1(rt,0);
        d2[rt]=is[rt]?(D2){0,rt,rt}:D2_nul;
        f2(rt);
        f3(rt);
        printf("%d %d
    ",ans,at);
        return 0;
    }
  • 相关阅读:
    [书目20130415]改变:28天让自己内心强大
    [引]软件著作权登记申请所需文件
    [转]动软代码生成器之模板功能介绍
    [转]C# 冒泡排序你还会吗?
    [转]细说ASP.NET Forms身份认证
    [转]listview加载性能优化ViewHolder
    [转]App for Android (2) —— Python篇
    [转]sqlserver 创建分区表
    [转]c# 四舍五入、上取整、下取整
    常用 Java 静态代码分析工具的分析与比较
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7504695.html
Copyright © 2011-2022 走看看