bzoj 3732: Network 樹上兩點邊權最值

來源:互聯網
上載者:User

標籤:std   --   href   遞迴   main   res   ble   lca   深度   

http://www.lydsy.com/JudgeOnline/problem.php?id=3732

首先想到,要使得最長邊最短,應該盡量走最短的邊,在MST上。

然後像LCA那樣倍增娶個最大值

#include <bits/stdc++.h>#define IOS ios::sync_with_stdio(false)using namespace std;#define inf (0x3f3f3f3f)typedef long long int LL;const int maxn = 30000 + 20;struct Edge {    int u, v, w, tonext;    bool operator < (const struct Edge & rhs) const {        return w < rhs.w;    }} e[maxn], t[maxn];int first[maxn], num;void addEdge(int u, int v, int w) {    e[num].u = u, e[num].v = v, e[num].w = w, e[num].tonext = first[u];    first[u] = num++;}int tfa[maxn];int tofind(int u) {    if (tfa[u] == u) return u;    else return tfa[u] = tofind(tfa[u]);}const int need = 20;int mx[maxn][25];int ansc[maxn][25], deep[maxn], fa[maxn];  //所有只需初始值,不需要初始化。void init_LCA(int cur) {   //1 << 20就有1048576(1e6)了。    ansc[cur][0] = fa[cur]; //跳1步,那麼祖先就是爸爸    if (cur != 1) {        for (int i = first[fa[cur]]; ~i; i = e[i].tonext) {            int v = e[i].v;            if (v == cur) {                mx[cur][0] = e[i].w;                break;            }        }    }    int haha = mx[cur][0];    for (int i = 1; i <= need; ++i) { //倍增思路,遞迴處理        ansc[cur][i] = ansc[ansc[cur][i - 1]][i - 1];        mx[cur][i] = mx[ansc[cur][i - 1]][i - 1];        mx[cur][i] = max(mx[cur][i], haha);        haha = max(haha, mx[cur][i]);  //上到極限的時候需要取個路經的最大值。    }    for (int i = first[cur]; ~i; i = e[i].tonext) {        int v = e[i].v;        if (v == fa[cur]) continue;        fa[v] = cur;        deep[v] = deep[cur] + 1;        init_LCA(v);    }}int LCA(int x, int y) {    int res = 0;    if (deep[x] < deep[y]) swap(x, y); //需要x是最深的    for (int i = need; i >= 0; --i) { //從大到小枚舉,因為小的更靈活        if (deep[ansc[x][i]] >= deep[y]) { //深度相同,走進去就對了。就是要去到相等。            res = max(res, mx[x][i]);            x = ansc[x][i];        }    }    if (x == y) return res;    for (int i = need; i >= 0; --i) {        if (ansc[x][i] != ansc[y][i]) { //走到第一個不等的地方,            res = max(res, mx[x][i]);            res = max(res, mx[y][i]);            x = ansc[x][i];            y = ansc[y][i];        }    }    res = max(res, mx[x][0]);    res = max(res, mx[y][0]);    return res; //再跳一步就是答案}void work() {    num = 0;    memset(first, -1, sizeof first);    int n, m, k;    scanf("%d%d%d", &n, &m, &k);    for (int i = 1; i <= n; ++i) tfa[i] = i;    for (int i = 1; i <= m; ++i) {        scanf("%d%d%d", &t[i].u, &t[i].v, &t[i].w);    }    sort(t + 1, t + 1 + m);    int sel = 0;    for (int i = 1; i <= m; ++i) {        if (sel == n - 1) break;        int x = tofind(t[i].u), y = tofind(t[i].v);        if (x == y) continue;        sel++;        tfa[y] = x;        addEdge(t[i].u, t[i].v, t[i].w);        addEdge(t[i].v, t[i].u, t[i].w);    }    fa[1] = 1, deep[1] = 0;    init_LCA(1);//    printf("%d\n", mx[2][1]);    for (int i = 1; i <= k; ++i) {        int u, v;        scanf("%d%d", &u, &v);        printf("%d\n", LCA(u, v));    }}int main() {#ifdef local    freopen("data.txt", "r", stdin);//    freopen("data.txt", "w", stdout);#endif    work();    return 0;}
View Code

 

bzoj 3732: Network 樹上兩點邊權最值

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.