Luogu 1099 树网的核

bzoj1999 数据加强版(n <= 5e5)
较早的noip题,值得研究
重要结论:直径的最长性,任何从直径中离开直径的点到它离开的点的距离,都不会比直径的另一端到它离开的点长(否则就有新的直径出现了嘛)
在求不经过直径的最长距离的时候犯错了,要考虑的是最远的点到现在点的距离,而不是只考虑儿子,码力还是太差……
包括代码的简洁性,多开了冗余的数组,都应当思考仔细

Code:

#include <cstdio>
using namespace std;

const int N = 5e5 + 5;

int n, s, tot = 0, head[N], fa[N], dis[N];
int pa = 1, pb = 1, maxv = 0, tmpMaxDis = 0;
bool vis[N];

struct Edge {
    int to, nxt, val;
} e[N << 1];

inline void add(int from, int to, int val) {
    e[++tot].to = to;
    e[tot].val = val;
    e[tot].nxt = head[from];
    head[from] = tot;
}

inline void read(int &X) {
    X = 0;
    char ch = 0;
    int op = 1;
    for(; ch > '9' || ch < '0'; ch = getchar())
        if(ch == '-') op = -1;
    for(; ch >= '0' && ch <= '9'; ch = getchar())
        X = (X << 3) + (X << 1) + ch - 48;
    X *= op;
}

inline int max(int x, int y) {
    return x > y ? x : y; 
}

inline int min(int x, int y) {
    return x > y ? y : x;
} 

void dfs(int x, int fat) {
    fa[x] = fat;
    for(int i = head[x]; i; i = e[i].nxt) {
        int y = e[i].to;
        if(y == fat) continue;
        dis[y] = dis[x] + e[i].val;
        dfs(y, x);
    }
}

inline void getDia() {
    dfs(1, 0);
    for(int i = 2; i <= n; i++)
        if(dis[pa] < dis[i]) pa = i; 
        
    dis[pa] = 0;
    dfs(pa, 0);
    for(int i = 2; i <= n; i++)
        if(dis[pb] < dis[i]) pb = i;
        
    for(int x = pb; x != 0; x = fa[x])
        vis[x] = 1;
}

void dfs2(int x, int ndis) {
    for(int i = head[x]; i; i = e[i].nxt) {
        int y = e[i].to;
        if(y == fa[x] || vis[y]) continue;
        tmpMaxDis = max(tmpMaxDis, ndis + e[i].val);
        dfs2(y, ndis + e[i].val);
    }
}

inline void getMaxDis() {
    for(int i = 1; i <= n; i++)
        if(vis[i]) {
            tmpMaxDis = 0;
            dfs2(i, 0);
            maxv = max(maxv, tmpMaxDis); 
        }        
}

int main() {
    read(n), read(s);
    for(int x, y, v, i = 1; i < n; i++) {
        read(x), read(y), read(v);
        add(x, y, v), add(y, x, v);
    }
    
    getDia();
    getMaxDis();
    
    int ans = 1 << 30;
/*    for(int i = pb; i; i = fa[i])
        maxv = max(maxv, maxDis[i]);
    
    for(int j = d.size() - 1, i = d.size() - 1; i >= 0; i--) {
        if(j != 0) 
            for(; j >= 0; j--) {
                if(dis[d[j]] - dis[d[i]] > s) {
                    j++;
                    break;
                }
            } 
        if(j == -1) j++;
        int tmp = max(maxv, max(dis[d[i]], dis[pb] - dis[d[j]]));
        ans = min(ans, tmp);
    } */
    
    for(int j = pb, i = pb; i; i = fa[i]) {
        for(; fa[j] && dis[i] - dis[fa[j]] <= s; j = fa[j]);
        int tmp = max(maxv, max(dis[j], dis[pb] - dis[i]));
        ans = min(ans, tmp);
    }
    
    printf("%d\n", ans);
    
    return 0;
}
原文地址:https://www.cnblogs.com/CzxingcHen/p/9466351.html