zoukankan      html  css  js  c++  java
  • 「NOI2003」逃学的小孩

    传送门:>HERE<

    题意:给出一棵树(带权),要从一个节点C先走到距离它近的一个节点B,再走到A,要求最坏情况下的总路程(即最长)。

    解题思路:

      乍一看,A,B,C都没给出,这怎么求?

      不妨设距离C较近的点位A。

      分析发现,无论怎样,A~B是一定要走的。那么如何能让树上任意两点间距离最大呢?不难发现A,B就是该树直径的两个端点。那么只要两遍BFS就好了。

      那么如何让A~C的路程最长呢?注意到A到C相较A到B是较短的。所以好像不怎么好求……但是可以枚举——枚举每个点作为C到A和B的距离,求出较小的那个,并且打擂得到最大值。

    Code

    /*By QiXingzhi*/
    #include <cstdio>
    #include <queue>
    #include <iostream>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #define  r  read()
    #define  Max(a,b)  (((a)>(b)) ? (a) : (b))
    #define  Min(a,b)  (((a)<(b)) ? (a) : (b))
    using namespace std;
    typedef long long ll;
    #define int ll
    const int N = 200010;
    const int INF = 1061109567;
    inline int read(){
        int x = 0; int w = 1; register int c = getchar();
        while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
        if(c == '-') w = -1, c = getchar();
        while(c >= '0' && c <= '9') x = (x << 3) +(x << 1) + c - '0', c = getchar();
        return x * w;
    }
    struct Edge{
        int to,cost;
    };
    int n,m,x,y,z,A,B,ans,ans2;
    int d[N], d2[N], vis[N];
    vector <Edge> G[N];
    queue <int> q;
    inline void AddEdge(int u, int v, int w){
        Edge e;
        e.to = v;
        e.cost = w;
        G[u].push_back(e);
    }
    inline void BFS(int s){
        while(!q.empty()) q.pop();
        q.push(s);
        d[s] = 0;
        vis[s] = 1;
        int cur,sz,v;
        while(!q.empty()){
            cur = q.front();
            q.pop();
            sz = G[cur].size();
            for(int i = 0; i < sz; ++i){
                v = G[cur][i].to;
                if(!vis[v]){
                    vis[v] = 1;
                    d[v] = d[cur] + G[cur][i].cost;
                    q.push(v);
                }
            }
        }
    }
    inline void BFS2(int s){
        while(!q.empty()) q.pop();
        q.push(s);
        d2[s] = 0;
        vis[s] = 1;
        int cur,sz,v;
        while(!q.empty()){
            cur = q.front();
            q.pop();
            sz = G[cur].size();
            for(int i = 0; i < sz; ++i){
                v = G[cur][i].to;
                if(!vis[v]){
                    d2[v] = d2[cur] + G[cur][i].cost;
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
    }
    main(){
        n = r, m = r;
        for(int i = 1; i <= m; ++i){
            x = r, y = r, z = r;
            AddEdge(x, y, z);
            AddEdge(y, x, z);
        }
        BFS(1);
        int __max = -100;
        for(int i = 1; i <= n; ++i){
            if(d[i] > __max){
                __max = d[i];
                A = i;
            }
        }
        ans = __max;
        memset(vis,0,sizeof(vis));
        BFS(A);
        __max = -100;
        for(int i = 1; i <= n; ++i){
            if(d[i] > __max){
                __max = d[i];
                B = i;
            }
        }
        ans = __max;
        memset(vis,0,sizeof(vis));
        BFS2(B);
        for(int i = 1; i <= n; ++i) ans2 = Max(ans2, Min(d[i], d2[i]));
        printf("%lld", ans+ans2);
        return 0;
    }
  • 相关阅读:
    Magic-Club第六天
    .net工具类——文件操作
    .net工具类——HTML处理
    .net工具类——随机生成
    .net工具类——删除最后结尾的一个逗号
    .net工具类——分割字符串
    .net工具类——对象转换处理
    .net扩展方法——其他(科学计数法、ToDictionary 去重、List<Guid>转为List<Guid?>)
    .net扩展方法——类型转换
    『Linux学习笔记』7. 管道和过滤器 -- pipe
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9342138.html
Copyright © 2011-2022 走看看