直径
題面
小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;
}
總結
- 上一篇: JQuery实现ajax批量上传图片
- 下一篇: Centos7.5 防火墙设置