• 直径


    题面

    小Q最近学习了一些图论知识。

    根据课本,有如下定义。

    树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度。

    如果一棵树有N个节点,可以证明其有且仅有N-1 条边。

    路径:一棵树上,任意两个节点之间最多有一条简单路径。

    我们用 dis(a,b)表示点a和点b的路径上各边长度之和。

    称dis(a,b)为a、b两个节点间的距离。

    直径:一棵树上,最长的路径为树的直径。

    树的直径可能不是唯一的。

    现在小Q想知道,对于给定的一棵树,其直径的长度是多少,以及有多少条边满足所有的直径都经过该边。

    输入格式

    第一行包含一个整数N,表示节点数。

    接下来N-1行,每行三个整数a, b, c ,表示点a和点b之间有一条长度为c的无向边。

    输出格式

    共两行。

    第一行一个整数,表示直径的长度。

    第二行一个整数,表示被所有直径经过的边的数量。

    数据范围

    2≤N≤200000,点的编号从1开始。
    c≤109
    

    输入样例:

    6 
    3 1 1000
    1 4 10
    4 2 100
    4 5 50
    4 6 100
    

    输出样例:

    1110
    2
    

    题解

    直径的相同路径必定连续, 好好画图思考一下(两次bfs,是怎么求出来直径的)

    所以我们首先求出来一条直径, 如果还存在另一条直径

    那么必定是, 再求出直径的某个点处走出一条分支, 且这条分支的长度和原来分支长度相等

    所以所求就是 上分叉, 一条直线, 下分叉 中直线包含有多少条路径

    就是在原直径p, q两个端点, 正和倒着求出 直径上两个端点 中间的路径唯一无分叉

    #include <bits/stdc++.h>
    #define all(n) (n).begin(), (n).end()
    #define se second
    #define fi first
    #define pb push_back
    #define mp make_pair
    #define sqr(n) (n)*(n)
    #define rep(i,a,b) for(int i=a;i<=(b);++i)
    #define per(i,a,b) for(int i=a;i>=(b);--i)
    #define IO ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef double db;
    
    const int N = 200005;
    
    int n, m, _, k;
    int h[N], ne[N << 1], co[N << 1], to[N << 1], tot;
    int f[N], b[N], dep[N], p, q, r, l;
    ll d[N], fd[N];
    set<int> st;
    
    void add(int u, int v, int c) {
        to[++tot] = v; ne[tot] = h[u]; h[u] = tot; co[tot] = c;
    }
    
    void dfs(int u, int fa) {
        for (int i = h[u]; i; i = ne[i]) {
            int y = to[i];
            if (y == fa) continue;
            f[y] = u; b[y] = i;
            dep[y] = dep[u] + 1;
            d[y] = d[u] + co[i];
            if (d[0] < d[y]) d[0] = d[y], f[0] = y;
            dfs(y, u);
        }
    }
    
    ll work(int& p, int& q) {
        d[0] = -1; dep[1] = d[1] = 0; dfs(1, 0); p = f[0];
        d[0] = -1; dep[p] = d[p] = 0; dfs(p, 0); q = f[0];
        return d[q];
    }
    
    void dfss(int u, int fa) {
        for (int i = h[u]; i; i = ne[i]) {
            int y = to[i];
            if (y == fa) continue;
            dfss(y, u);
            fd[u] = max(fd[u], fd[y] + co[i]);
            if (!st.count(u) || st.count(y)) continue;
            if (d[q] - d[u] == fd[y] + co[i]) r = u;
            if (d[u] == fd[y] + co[i] && dep[l] < dep[u]) l = u;
        }
    }
    
    int main() {
        IO; cin >> n;
        rep(i, 2, n) {
            int u, v, c; cin >> u >> v >> c;
            add(u, v, c); add(v, u, c);
        }
        cout << work(p, q) << '
    ';
    
        st.insert(p);
        for (int i = q; i != p; st.insert(i), i = f[i]);
        r = q, l = p; dfss(p, 0);
        cout << max(0, dep[r] - dep[l]);
        return 0;
    }
    
  • 相关阅读:
    hdu2860 并查集模拟
    hdu 3938 Portal离线并查集
    hdu 2489 Minimal Ratio Tree (DFS枚举+MST)
    hdu 3172 并查集+map
    hdu 1829 A Bug's Life 并查集系列
    hdu 1598 find the most comfortable road
    HDU1198
    【Oracle】【17】表创建后,对表进行操作(添加字段,删除主键约束等)
    【JS】【19】使用Jquery判断是电脑或手机或微信浏览器访问
    【JS】【18】当前时间加减一天和格式化时间格式
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/13571771.html
Copyright © 2020-2023  润新知