• SCUT


    https://scut.online/p/274

    首先要判断是一颗树,并且找出树的直径。

    是一棵树,首先边恰好有n-1条,其次要连通,这两个条件已经充分了,当然判环可以加速。

    两次dfs找出直径,一边叫做L,另一边叫做R。(第一次写这个)

    然后树形dp。

    规定其中一个叶子作为树根。然后fx表示从x向下(叶子)走能走到的最远距离,这个非常简单。

    然后漏了什么情况呢?从x向上走的情况。

    这个时候要从根开始维护一个叫做gx的数组,那么每次孩子v的gx就是父亲u的gx(继续向上走)和u的fx(从父亲开始往下走)的最大值。注意这个时候往下走的不能走回去v,所以要记录两个fx,并且记录大的那个是走哪个方向的。

    边界:在叶子/树根等不能走的位置,根据定义,距离为0,点序号为本身。

    #include<bits/stdc++.h>
    using namespace std;
    
    const int MAXN = 1e5 + 5;
    const int INF = 0x3f3f3f3f;
    
    struct Edge {
        int v, w;
    };
    
    vector<Edge> e[MAXN];
    
    void init0(int n) {
        for(int i = 0; i <= n; ++i)
            e[i].clear();
    }
    
    int cnt, vis[MAXN], dis[MAXN], maxdis, L, R;
    
    void init1(int n) {
        memset(vis, false, sizeof(vis[0]) * (n + 1));
        memset(dis, 0, sizeof(dis[0]) * (n + 1));
        cnt = 0, maxdis = 0;
    }
    
    bool dfs1(int id, int fa) {
        vis[id] = true, ++cnt;
        for(auto p : e[id]) {
            int v = p.v, w = p.w;
            if(v == fa)
                continue;
            if(vis[v])
                return false;
            dis[v] = dis[id] + w;
            if(dis[v] > maxdis)
                maxdis = dis[v], L = v;
            if(dfs1(v, id) == false)
                return false;
        }
        return true;
    }
    
    void init2(int n) {
        memset(dis, 0, sizeof(dis[0]) * (n + 1));
        maxdis = 0;
    }
    
    void dfs2(int id, int fa) {
        for(auto p : e[id]) {
            int v = p.v, w = p.w;
            if(v == fa)
                continue;
            dis[v] = dis[id] + w;
            if(dis[v] > maxdis)
                maxdis = dis[v], R = v;
            dfs2(v, id);
        }
    }
    
    struct F {
        int v, w, s;
        F(int v = 0, int w = 0, int s = 0): v(v), w(w), s(s) {}
    } f[MAXN], f2[MAXN], tmp;
    
    void maintainF(int id) {
        if(tmp.w > f2[id].w || tmp.w == f2[id].w && tmp.v < f2[id].v) {
            f2[id] = tmp;
            if(f2[id].w > f[id].w || f2[id].w == f[id].w && f2[id].v < f[id].v)
                swap(f[id], f2[id]);
        }
    }
    
    void dfs3(int id, int fa) {
        f[id] = f2[id] = F(id, 0, -1);
        for(auto p : e[id]) {
            int v = p.v, w = p.w;
            if(v == fa)
                continue;
            dfs3(v, id);
            tmp.w = f[v].w + w, tmp.v = f[v].v, tmp.s = v;
            maintainF(id);
        }
    }
    
    struct G {
        int v, w;
    } g[MAXN];
    
    F getF(int id, int fa) {
        if(f[fa].s == id)
            return f2[fa];
        return f[fa];
    }
    
    void maintainG(int id, int fa, int faw) {
        if(fa == 0) {
            g[id].w = 0;
            g[id].v = id;
            return;
        }
        tmp = getF(id, fa);
        if(g[fa].w > tmp.w) {
            g[id].w = g[fa].w + faw;
            g[id].v = g[fa].v;
        } else if(g[fa].w == tmp.w) {
            g[id].w = g[fa].w + faw;
            g[id].v = min(tmp.v, g[fa].v);
        } else {
            g[id].w = tmp.w + faw;
            g[id].v = tmp.v;
        }
    }
    
    void dfs4(int id, int fa, int faw) {
        maintainG(id, fa, faw);
        for(auto p : e[id]) {
            int v = p.v, w = p.w;
            if(v == fa)
                continue;
            dfs4(v, id, w);
        }
    }
    
    int getFG(int id) {
        if(f[id].w > g[id].w)
            return f[id].v;
        else if(f[id].w == g[id].w)
            return min(f[id].v, g[id].v);
        return g[id].v;
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n, m, k;
        while(~scanf("%d%d%d", &n, &m, &k)) {
            if(m != n - 1) {
                for(int i = 1, u, v, w; i <= m; ++i)
                    scanf("%d%d%d", &u, &v, &w);
                puts("There is no B-Tree");
                continue;
            }
            init0(n);
            for(int i = 1, u, v, w; i <= m; ++i) {
                scanf("%d%d%d", &u, &v, &w);
                e[u].push_back({v, w});
                e[v].push_back({u, w});
            }
            init1(n);
            if(dfs1(1, 0) == false || cnt != n) {
                puts("There is no B-Tree");
                continue;
            }
            init2(n);
            dfs2(L, 0);
            if(dis[R] > k) {
                puts("There is no B-Tree");
                continue;
            }
            dfs3(R, 0);
            dfs4(R, 0, 0);
            for(int i = 1; i <= n; ++i)
                printf("%d
    ", getFG(i));
        }
    }
    
  • 相关阅读:
    Java Learning (201108025)
    Java Learning (20110808)
    Negative numbers and binary representation
    “this” pointer
    NullPointerException
    Special Swiss Education
    Java Learning (20110802)
    More about Swiss keyboard
    About memory leak
    Application Verifier
  • 原文地址:https://www.cnblogs.com/Yinku/p/11308595.html
Copyright © 2020-2023  润新知