• 连通能力


    Star 善于胡思乱想,这些天他又为带权树定义了一个叫"连通能力"的奇怪属性。对于一棵边上有权值的树(N 个
    结点 N - 1 条边的无向连通图),我们按以下方法定义其连通能力:
    1、规定某结点的代价为它到其它结点的距离(简单路径所经过边的权值和)的最大值;
    2、代价最小的结点的代价作为这棵树的连通能力。
    设某棵给定的树以 1 号结点为根,Star 想考察以任意结点为根的子树的连通能力有多大。
    请你帮助他把这 N 个值快速求出来。
    Input
    第一行一个整数 N;
    接下来 N - 1 行,每行三个整数 u、v、w 表示结点 u、v 间存在权值为 w 的边。
    1 ≤ N ≤ 1000000、1 ≤ w ≤ 10000。
    Output
    输出 N 行 N 个整数,第 i 行的值表示以结点 i 为根的子树所对应的连通能力
    input
    6
    1 2 2
    1 3 8
    2 4 4
    2 5 6
    4 6 3
    output
    9
    7
    0
    3
    0
    0

    /*
    需要证明几个东西
    1:以叶子点的根是树,答案是0
    2: 对于非叶子点的树,答案必须是它的某个非叶子点
    3:这个非叶子点在树的直径上,因为如果不在直径上,那么其必与直径上某个点a相连的,也必然没有a更优
    4:树的直径可能并不经过根,直接从某个子树继承过来
    5:所求的点在直径上,设直径的两个点为dep1[x],dep2[x]
    呈现这样一种形式dep1[x].........j................dep2[x]
    其中的j点,为一个我们从dep1[x]开始跳的点,尽量向右跳,但 [j,dep2[x]]>=[dep1[x],j]
    这样跳出来后较大值始终为 [j,dep2[x]],但还有一种可能就是
    dep1[x].........j...fa[j]............dep2[x]
    值也可能为[dep1[x],fa[j],所以求两者的较小值
    */
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define L 25
    #define N 1000005
    #define M 2000005
    using namespace std;
    int t,first[N],v[M],w[M],nextt[M],father[N][L];
    int d[N],r[N],f1[N],f2[N],dis[N],dep1[N],dep2[N];
    void add(int x,int y,int z)
    {
    t++;
    nextt[t]=first[x];
    first[x]=t;
    v[t]=y;
    w[t]=z;
    }
    inline void getfather(int x)
    {
    int i,j;
    for(i=first[x];i;i=nextt[i])
    {
    j=v[i];
    if(j==father[x][0])
    continue;
    father[j][0]=x;
    getfather(j);
    }
    }
    inline void search(int x)
    {
    int i,j,depth;
    dep1[x]=x;//x的最长链对应的端点
    dep2[x]=x;//x的次长链对应的端点
    for(i=first[x];i;i=nextt[i])
    {
    j=v[i];
    if(j==father[x][0])
    continue;
    dis[j]=dis[x]+w[i];//j到根的距离
    search(j);
    if(r[j]>r[x])//直径在以j为根的子树中
    {
    d[x]=d[j];
    r[x]=r[j];
    }
    if(f1[x]<f1[j]+w[i])//更新最长链及次长链及端点信息
    {
    f2[x]=f1[x];
    dep2[x]=dep1[x];
    f1[x]=f1[j]+w[i];
    dep1[x]=dep1[j];
    }
    else if(f2[x]<f1[j]+w[i])
    {
    f2[x]=f1[j]+w[i];
    dep2[x]=dep1[j];
    }
    }
    depth=dep1[x];//从最长链的那个端点来跳
    if(d[x]<f1[x]+f2[x])
    {
    d[x]=f1[x]+f2[x];
    for(i=20;i>=0;--i)
    if(depth!=x&&(f2[x]+dis[father[depth][i]]-dis[x]>=f1[x]-dis[father[depth][i]]+dis[x]))
    //让depth尽量向上跳,所到的点必须满足[次长链端点,所跳点]>=[最长链端点,所跳点]
    depth=father[depth][i];
    r[x]=f2[x]+dis[depth]-dis[x];
    //dep1[x].........x.......x的父亲点.......dep2[x]
    //所求半径可能为[x,dep2[x]
    if(depth!=x&&f1[x]-dis[father[depth][0]]+dis[x]<r[x])
    //所求半径也可能为[dep1[x],x的父亲点],应取其中的较小值
    r[x]=f1[x]-dis[father[depth][0]]+dis[x];
    }
    }
    int main()
    {

    int n,i,j,x,y,z;
    scanf("%d",&n);
    for(i=1;i<n;++i)
    {
    scanf("%d%d%d",&x,&y,&z);
    add(x,y,z);
    add(y,x,z);
    }
    getfather(1);
    for(j=1;j<=20;++j)
    for(i=1;i<=n;++i)
    father[i][j]=father[father[i][j-1]][j-1];
    search(1);
    for(i=1;i<=n;++i)
    cout<<r[i]<<'\n';
    return 0;
    }
    //*
    6
    1 2 2
    1 3 8
    2 4 4
    2 5 6
    4 6 3
    9
    7
    0
    3
    0
    0
    //

      

  • 相关阅读:
    jenkins代码自动部署
    jenkins安装
    git图形管理工具
    gitlab自动备份恢复与卸载
    linux下获取外网IP
    网站安全webshell扫描
    jQuery动画效果实现
    form表单中的enctype属性什么意思?
    你那么努力又怎么样!
    话语
  • 原文地址:https://www.cnblogs.com/cutemush/p/11743768.html
Copyright © 2020-2023  润新知