最近公共祖先 次小生成樹

2021-10-05 04:33:26 字數 1842 閱讀 9053

給定一張 n 個點 m 條邊的無向圖,求無向圖的嚴格次小生成樹。

設最小生成樹的邊權之和為sum,嚴格次小生成樹就是指邊權之和大於sum的生成樹中最小的乙個。

輸入格式

第一行包含兩個整數n和m。

接下來m行,每行包含三個整數x,y,z,表示點x和點y之前存在一條邊,邊的權值為z。

輸出格式

包含一行,僅乙個數,表示嚴格次小生成樹的邊權和。(資料保證必定存在嚴格次小生成樹)

資料範圍

n≤105,m≤3∗105n≤105,m≤3∗105

輸入樣例:

5 61 2 1

1 3 2

2 4 3

3 5 4

3 4 3

4 5 6

輸出樣例:

11

#include

#include

#include

#include

using

namespace std;

const

int n =

100010

, m =

300010

, inf =

0x3f3f3f3f

;int n, m;

typedef

long

long ll;

struct edge

}edge[m]

;int p[n]

;int h[n]

, e[m]

, w[m]

, ne[m]

, idx;

int depth[n]

, fa[n][17

], d1[n][17

], d2[n][17

];int q[n]

;int

find

(int x)

void

add(

int a,

int b,

int c)

void

build()

}ll kruskal()

}return res;

}void

bfs();

d1[j]

[k]= d2[j]

[k]=

-inf;

for(

int u =

0; u <

4; u++)}

}}}}

intlca

(int a,

int b,

int w)

if(a != b)

distance[cnt++

]= d1[a][0

];distance[cnt++

]= d1[b][0

];}int dist1 =

-inf, dist2 =

-inf;

for(

int i =

0; i < cnt; i++)if

(w > dist1)

return w - dist1;

if(w > dist2)

return w - dist2;

return inf;

}int

main()

;}ll sum =

kruskal()

;build()

;bfs()

; ll res =

1e18

;for

(int i =

0; i < m; i++)}

printf

("%lld\n"

, res)

;return0;

}

BZOJ 1977 次小生成樹(最近公共祖先)

題意 求一棵樹的嚴格次小生成樹,即權值嚴格大於最小生成樹且權值最小的生成樹。思路 若現在已經得到了最小生成樹,那麼若 新增一條邊e,就會得到乙個環,我們只需要去掉環上權值小於e且最大的一條邊就會得到另一棵較優的生成樹。因此,只需要列舉不在生成樹上的邊,計算將其添 加到最小生成樹中得到的新生成樹的權值...

BZOJ 1977 次小生成樹(最近公共祖先)

題意 求一棵樹的嚴格次小生成樹,即權值嚴格大於最小生成樹且權值最小的生成樹。先求最小生成樹,對於每個不在樹中的邊,取兩點間路徑的資訊,如果這條邊的權值等於路徑中的權值最大值,那就刪掉路徑中的次大值,加上這條非樹邊,更新答案 否則刪掉路徑中的最大值,加上這條非樹邊,更新答案。1 include2 in...

最近公共祖先 python 最近公共祖先

lca演算法樸素演算法 也就是我們所說的暴力演算法,大致的思路是從樹根開始,往下迭代,如果當前結點比兩個結點都小,那麼說明要從樹的右子樹中找 相反則從左子樹中查詢 直到找到乙個結點在當前結點的左邊,乙個在右邊,說明當前結點為最近公共祖先,如果乙個結點是另外乙個結點的祖先,那麼返回前面結點的父親結點即...