1 条题解

  • 0
    @ 2025-8-24 21:47:32

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 破壁人
    **

    搬运于2025-08-24 21:47:32,当前版本为作者最后更新于2018-01-04 19:49:51,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    首先求出直径这个简单,只要dfs一遍就行了。

    我们再考虑第二问。要求的是所有直径都经过的边数。

    所以我们先任意求出一条直径,记录这条直径上的点。

    再对每个直径上的点都dfs,求出以这个点为起点的最长链(当然不能包括直径上的其它点),长度用dis[i]表示。

    ls[i]表示这个点到直径左端点的距离。

    rs[i]表示这个点到直径右端点的距离。(左右随意定)

    从左端点开始向右遍历直径,若到了j号点发现,dis[j]=rs[j]就可以跳出循环,因为j的右边的所有边都不可能是必经边。

    因为我们找到了一条不经过它们的直径。

    那么是不是左端点到j就是必经边了呢?显然不是的。

    因为还有可能出现这种情况,即dis[k]=ls[k],这样就变成了k的左边的所有边都不可能是必经边。

    所以我们还要类似的从刚才跳出循环的点开始向左寻找这个k点。

    那么j到k的所有边就是必经边了。

    #include<iostream>
    #include<vector>
    #include<cstring>
    using namespace std;
    vector<int> a[200001],b[200001];
    int last[200001],u,v,next[200001];
    long long dis[200001],mmm[200001],op;
    bool vv[200001];
    void dfs1(int o,long long p,int q)
    {
        if(p>op){op=p;u=o;}
        for(int i=0;i<a[o].size();i++)
            if((!vv[a[o][i]])&&(a[o][i]!=q))
            {
                vv[a[o][i]]=true;
                dfs1(a[o][i],p+b[o][i],o);
            }
    }
    void dfs2(int o,long long p,int q)
    {
        last[o]=q;
        dis[o]=p;
        if(p>op){op=p;v=o;}
        for(int i=0;i<a[o].size();i++)
            if((!vv[a[o][i]])&&(a[o][i]!=q))
            {
                vv[a[o][i]]=true;
                dfs2(a[o][i],p+b[o][i],o);
            }
    }
    int main()
    {
        int n;
        cin>>n;
        for(int i=1;i<n;i++)
        {
            int x,y,z;
            cin>>x>>y>>z;
            a[x].push_back(y);
            b[x].push_back(z);
            a[y].push_back(x);
            b[y].push_back(z);
        }
        memset(vv,0,sizeof(vv));op=0;
        dfs1(1,0,0);
        memset(vv,0,sizeof(vv));op=0;
        dfs2(u,0,0);
        int distance=dis[v];
        cout<<dis[v]<<endl;
        memset(vv,0,sizeof(vv));
        for(int i=v;i!=0;i=last[i]) vv[i]=true;
        for(int i=v;i!=0;i=last[i])
        {
            op=0;
            dfs1(i,0,0);
            mmm[i]=op;
        }
        int j=v;
        for(int i=last[v];i!=0;i=last[i]) next[i]=j,j=i;
        int ans=0;
        int i;
        for(i=j;i!=0;i=next[i])
            if(dis[v]-dis[i]==mmm[i]) break;
        for(;i!=0;i=last[i])
        {
            if(dis[i]==mmm[i]) break;
            ans++;
        }
        cout<<ans<<endl;
        return 0;
    }
    
    • 1

    信息

    ID
    2377
    时间
    1000ms
    内存
    125MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者