zoukankan      html  css  js  c++  java
  • [BZOJ 1509] 逃学的小孩

    Link:

    BZOJ 1509 传送门

    Solution:

    一开始受样例影响又犯了想当然的毛病……图中的C点不一定在直径上!

    3次$dfs$求出树的直径及直径的两个端点$rt1,rt2$到每个点的距离$d1,d2$,

    则结果为$max{ Diameter+min{ d1[i],d2[i] } }$

    Tips:如果要求出直径上每个点或求点到直径端点的距离时,最好还是用2次$dfs$的方法,而不使用一遍$dfs$法

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int MAXN=2e5+10;
    struct edge{int to,nxt,w;}e[MAXN<<2];
    int n,m,rt1,rt2,head[MAXN],tot=-1;
    ll d1[MAXN],d2[MAXN],dia=0,res=0;
    
    void add_edge(int x,int y,int z)
    {
        e[++tot].nxt=head[x];e[tot].to=y;e[tot].w=z;head[x]=tot;
        e[++tot].nxt=head[y];e[tot].to=x;e[tot].w=z;head[y]=tot;
    }
    
    void dfs(int x,int anc)
    {
        for(int i=head[x];i!=-1;i=e[i].nxt)
        {
            if(e[i].to==anc) continue;
            d1[e[i].to]=max(d1[e[i].to],d1[x]+e[i].w);
            dfs(e[i].to,x);
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        memset(head,-1,sizeof(head));d1[0]=-1e15;
        for(int i=1;i<=m;i++)
        {
            int x,y,z;scanf("%d%d%d",&x,&y,&z);
            add_edge(x,y,z);
        }
        
        dfs(1,0);for(int i=1;i<=n;i++) if(d1[i]>d1[rt1]) rt1=i;
        memset(d1,0,sizeof(d1));d1[0]=-1e15;dfs(rt1,0);
        for(int i=1;i<=n;i++)
        {
            if(d1[i]>d1[rt2]) rt2=i;
            d2[i]=d1[i];dia=max(dia,d1[i]);
        }
        memset(d1,0,sizeof(d1));dfs(rt2,0);
        
        for(int i=1;i<=n;i++)
            res=max(res,dia+min(d1[i],d2[i]));
        printf("%lld",res);
        return 0;
    }
  • 相关阅读:
    html JS 开发备忘
    C++学习备忘(一)
    博客开通备忘
    自己制作的代码生成工具AutoCoder
    C# 小技巧
    突破list存为模板为10M限制
    开博
    OpenEuler中C语言中的函数调用测试
    socket测试3
    电子公文传输系统验收4开发基础
  • 原文地址:https://www.cnblogs.com/newera/p/9232303.html
Copyright © 2011-2022 走看看