• BZOJ1509: [NOI2003]逃学的小孩


    1509: [NOI2003]逃学的小孩

    这里写图片描写叙述
    Input

    第一行是两个整数N(3  N 
    200000)和M,分别表示居住点总数和街道总数。

    下面M行,每行给出一条街道的信息。

    第i+1行包括整数Ui、Vi、Ti(1Ui, Vi 
    N。1  Ti  1000000000),表示街道i连接居住点Ui和Vi,而且经过街道i需花费Ti分钟。街道信息不会反复给出。

    Output

    仅包括整数T。即最坏情况下Chris的父母须要花费T分钟才干找到Chris。

    Sample Input

    4 3

    1 2 1

    2 3 1

    3 4 1

    Sample Output
    4

    题解:

    依照题意理解,找出3条路径a,b,c.(a>b>c)
    答案就是(a+2*b+c)
    树形dp,两次dfs
    先以儿子dp。找出最大。中间,最小。
    可是父亲所在的链也是一条链。所以须要第二次dfs,推断父亲所在的链。
    代码:

    /**************************************************************
        Problem: 1509
        User: wjyi
        Language: C++
        Result: Accepted
        Time:1188 ms
        Memory:13208 kb
    ****************************************************************/
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int maxn=200005;
    struct Node{
        int to,next,w;
    }e[maxn<<1];
    int tot,head[maxn],n,m;
    ll mx1[maxn],mx2[maxn],mx3[maxn],f[maxn],ans;
    bool vis[maxn];
    void add(int u,int v,int w){
        e[++tot]=(Node){v,head[u],w};head[u]=tot;
    }
    void dfs(int x){
        vis[x]=1;mx1[x]=mx2[x]=0;
        for(int i=head[x];i;i=e[i].next)if(!vis[e[i].to]){
              dfs(e[i].to);
              mx3[x]=max(mx3[x],mx1[e[i].to]+e[i].w);
              if(mx3[x]>mx2[x])swap(mx3[x],mx2[x]);
              if(mx2[x]>mx1[x])swap(mx1[x],mx2[x]);
            }
    }
    void dfs1(int x){
        vis[x]=1;
        for(int i=head[x];i;i=e[i].next)
          if(!vis[e[i].to]){
            f[e[i].to]=f[x]+e[i].w;
            if(mx1[e[i].to]+e[i].w==mx1[x])
              f[e[i].to]=max(f[e[i].to],mx2[x]+e[i].w);
            else
              f[e[i].to]=max(f[e[i].to],mx1[x]+e[i].w);
            dfs1(e[i].to);
          }
    }
    void update(ll &x,ll &y,ll &z){
        if(y>x)swap(x,y);
        if(z>x)swap(x,z);
        if(z>y)swap(y,z);
        ans=max(ans,x+(y<<1)+z);
    }
    int main(){
        scanf("%d%d",&n,&m);
        int u,v,w;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);add(v,u,w);
        }
        memset(vis,0,sizeof(vis));
        dfs(1);
        memset(vis,0,sizeof(vis));
        dfs1(1);
        ans=0;
        for(int i=1;i<=n;i++)
          f[i]<=mx3[i]?update(mx1[i],mx2[i],mx3[i]):update(mx1[i],mx2[i],f[i]);
        printf("%lld
    ",ans);
        return 0;
    } 
  • 相关阅读:
    C++ 类 构造函数 constructor
    数据库——关系代数
    海明码
    C++ this指针
    C++ 类的定义与实现
    C++ 函数 内联函数
    C++ 函数 函数的重载 有默认参数的函数
    2017年第八届蓝桥杯【C++省赛B组】
    2018年第九届蓝桥杯【C++省赛B组】
    C++ 函数 参数传递方式
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/7259874.html
Copyright © 2020-2023  润新知