直径 题面 输入格式 输出格式 数据范围 输入样例: 输出样例: 题解

小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;
}