zoukankan      html  css  js  c++  java
  • 求树上每个节点可以走到的最远距离

    1073. 树的中心

    给定一棵树,树中包含 n 个结点(编号1~n)和 n−1 条无向边,每条边都有一个权值。
    请你在树中找到一个点,使得该点到树中其他结点的最远距离最近。
    输入格式
    第一行包含整数 n。
    接下来 n−1 行,每行包含三个整数 ai,bi,ci,表示点 ai 和 bi 之间存在一条权值为 ci 的边。
    输出格式
    输出一个整数,表示所求点到树中其他结点的最远距离。
    数据范围
    1≤n≤10000,
    1≤ai,bi≤n,
    1≤ci≤105
    输入样例:
    5
    2 1 1
    3 2 1
    4 3 1
    5 1 1
    输出样例:
    2

    第一次DFS求每个节点通过直接点的最远距离max1以及该儿子,并且还需要求一个次远距离max2。然后再求通过父节点可以到达的最远距离max3,可以是合并父节点的max1或max2或max3,但是当父节点的max1的儿子是该节点时,就不能合并,只能尝试合并max2,这就是记录次远距离的作用

    #include<bits/stdc++.h>
    using namespace std;
    const int N=10010;
    int head[N],cnt,ans;
    struct eg{
        int v,c,nex;
    }edge[N*2];
    int Max1[N],Max2[N],Max3[N];
    int son1[N];
    void addedge(int u,int v,int c){
        edge[cnt]=(eg){v,c,head[u]};
        head[u]=cnt++;
    }
    void dfs1(int u,int pre){
        for(int i=head[u];~i;i=edge[i].nex){
            int v=edge[i].v,c=edge[i].c;
            if(pre==v) continue;
            dfs1(v,u);
            if(c+Max1[v]>=Max1[u]){
                Max2[u]=Max1[u];
                Max1[u]=c+Max1[v];
                son1[u]=v;
            }
            else if(c+Max1[v]>Max2[u]){
                Max2[u]=c+Max1[v];
            }
        }
        //cout<<u<<" "<<Max1[u]<<" "<<son1[u]<<"--"<<Max2[u]<<" "<<son2[u]<<endl;
    }
    void dfs2(int u,int pre){
        for(int i=head[u];~i;i=edge[i].nex){
            int v=edge[i].v,c=edge[i].c;
            if(pre==v) continue;
    
            if(son1[u]!=v){
                Max3[v]=Max1[u]+c;
            }
            else {
                Max3[v]=Max2[u]+c;
            }
            Max3[v]=max(Max3[u]+c,Max3[v]);
            dfs2(v,u);
        }
    }
    int main(){
        int n;
        cin>>n;
        memset(head,-1,sizeof head);
        for(int i=1,u,v,c;i<n;++i){
            cin>>u>>v>>c;
            addedge(u,v,c);
            addedge(v,u,c);
        }
        dfs1(1,0);
        dfs2(1,0);
        int ans=1000000000;
        for(int i=1;i<=n;++i)
            ans=min(ans,max(Max1[i],max(Max2[i],Max3[i])));
        cout<<ans<<endl;
        return 0;
    }
    

    325. 计算机

    一所学校前一段时间买了第一台计算机(所以这台计算机的ID是1)。
    近年来,学校又购买了N-1台新计算机。
    每台新计算机都与之前买进的计算机中的一台建立连接。
    现在请你求出第i台计算机到距离其最远的计算机的电缆长度。

    例如,上图中距离计算机1最远的是计算机4,因此 S1=3;距离计算机2最远的是计算机4和5,因此 S2=2;距离计算机3最远的是计算机5,所以 S3=3;同理,我们也得到 S4=4,S5=4。
    输入格式
    输入包含多测试数据。
    每组测试数据第一行包含整数N。
    接下来N-1行,每行包含两个整数,第 i 行的第一个整数表示第 i 台电脑买入时连接的电脑编号,第二个整数表示这次连接花费的电缆长度。
    输出格式
    每组测试数据输出N行。
    第i行输出第i台电脑的Si。
    数据范围
    1≤N≤10000,
    电缆总长度不超过109
    输入样例:
    5
    1 1
    2 1
    3 1
    1 1
    输出样例:
    3
    2
    3
    4
    4

    带上边权

    #include<bits/stdc++.h>
    using namespace std;
    const int N=10010;
    int head[N],cnt,ans;
    struct eg{
        int v,c,nex;
    }edge[N*2];
    int Max1[N],Max2[N],Max3[N];
    int son1[N],son2[N];
    void addedge(int u,int v,int c){
        edge[cnt]=(eg){v,c,head[u]};
        head[u]=cnt++;
    }
    void dfs1(int u,int pre){
        for(int i=head[u];~i;i=edge[i].nex){
            int v=edge[i].v,c=edge[i].c;
            if(pre==v) continue;
            dfs1(v,u);
            if(c+Max1[v]>=Max1[u]){
                Max2[u]=Max1[u];
                son2[u]=son1[u];
                Max1[u]=c+Max1[v];
                son1[u]=v;
            }
            else if(c+Max1[v]>Max2[u]){
                Max2[u]=c+Max1[v];
                son2[u]=v;
            }
        }
        //cout<<u<<" "<<Max1[u]<<" "<<son1[u]<<"--"<<Max2[u]<<" "<<son2[u]<<endl;
    }
    void dfs2(int u,int pre){
        for(int i=head[u];~i;i=edge[i].nex){
            int v=edge[i].v,c=edge[i].c;
            if(pre==v) continue;
    
            if(son1[u]!=v){
                Max3[v]=Max1[u]+c;
            }
            else {
                Max3[v]=Max2[u]+c;
            }
            Max3[v]=max(Max3[u]+c,Max3[v]);
            dfs2(v,u);
        }
    }
    int main(){
        int n;
        cin>>n;
        memset(head,-1,sizeof head);
        for(int i=2,u,v,c;i<n;++i){
            cin>>u>>v>>c;
            addedge(u,v,c);
            addedge(v,u,c);
        }
        dfs1(1,0);
        dfs2(1,0);
        int ans=1000000000;
        for(int i=1;i<=n;++i)
            ans=min(ans,max(Max1[i],max(Max2[i],Max3[i])));
        cout<<ans<<endl;
        return 0;
    }
    

    齐心抗疫


    由于最终的答案一定是某个点a被另一个点b帮助,距离a最远的点就一定是b,且b点值一定小于a,如果大于a,那么答案就应该是b点值乘与一个距离大于等于a的距离,答案就会更大。所以只要找到每个点的可以走到的最远距离乘再与他的点值像乘法,就能够找到点a并更新答案

    #include<bits/stdc++.h>
    using namespace std;
    const int N=50010;
    int fw[N],h[N],tot,max1[N],max2[N],son1[N],p[N];
    struct eg{
        int v,nex;
    }e[N*2];
    void add(int u,int v){
        e[tot]=(eg){v,h[u]};
        h[u]=tot++;
    }
    void dfs1(int u,int pre){
        son1[u]=u;
        max1[u]=max2[u]=0;
        for(int i=h[u];~i;i=e[i].nex){
            int v=e[i].v,c=1;
            if(pre==v) continue;
            dfs1(v,u);
            if(max1[v]+c>max1[u]){
                max2[u]=max1[u];
                max1[u]=max1[v]+c;
                son1[u]=son1[v];
            }
            else if(max1[v]+c>max2[u]){
                max2[u]=max1[v]+c;
            }
        }
    }
    void dfs2(int u,int pre){
        for(int i=h[u];~i;i=e[i].nex){
            int v=e[i].v,c=1;
            if(v==pre) continue;
            fw[v]=0;
            if(son1[u]!=son1[v]&&fw[v]<max1[u]+c){
                fw[v]=max1[u]+c;
            }
            else if(fw[v]<max2[u]+c){
                fw[v]=max2[u]+c;
            }
            if(fw[v]<fw[u]+c){
                fw[v]=fw[u]+c;
            }
            dfs2(v,u);
        }
    }
    int main(){
        int n;
        memset(h,-1,sizeof h);
        cin>>n;
        for(int i=1;i<=n;++i) cin>>p[i];
        for(int i=2;i<=n;++i){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        dfs1(1,0);
        dfs2(1,0);
        int res=0;
        for(int i=1;i<=n;++i){
            res=max(res,p[i]*max(max1[i],fw[i]));
        }
        cout<<res<<endl;
        return 0;
    }
    
  • 相关阅读:
    Revit 二次开发 几何
    Revit 二次开发 元素过滤练习
    Revit 二次开发 图元过滤
    Revit 二次开发 图元与参数
    扩展Revit的方式
    Revit API二次开发入门,完整学习流程,附源码
    Revit 二次开发学习视频
    在lldb调试中调用c++函数
    在lldb调试中调用c++函数
    lldb调试使用python脚本问题总结
  • 原文地址:https://www.cnblogs.com/jjl0229/p/12652455.html
Copyright © 2011-2022 走看看