日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

直径

發布時間:2024/6/21 综合教程 30 生活家
生活随笔 收集整理的這篇文章主要介紹了 直径 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題面

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

總結

以上是生活随笔為你收集整理的直径的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。