AcWing 356 次小生成樹

2022-09-10 04:57:14 字數 1787 閱讀 6944

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

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

輸入格式: 第一行包含兩個整數$n$和$m$。 接下來$m$行,每行包含三個整數$x,y,z$,表示點$x$和點$y$之前存在一條邊,邊的權值為$z$。

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

資料範圍:$n\leqslant 10^5,m\leqslant 3\times10^5$。

分析:我們先求出原圖的最小生成樹,然後列舉每一條非樹邊,看看當前兩點構成的路徑上最大邊與次大邊與該非樹邊的大小關係,由於求出的最小生成樹是選出的最短邊,因此非樹邊一定滿足大於等於這兩點路徑上的所有邊,當然也滿足大於等於最大邊。若等於最大邊,則我們將次大邊替換成非樹邊,否則替換最大邊為非樹邊。樹上兩點路徑上的最大邊與次大邊可以在求$\mathrm$時也求出來,具體地,我們設$g[x][y][0]$表示點$x$向上走$2^y$步中的次大邊,$g[x][y][1]$表示點$x$向上走$2^y$步中的最大邊。那麼我們可以先求出走到$2^$點的最大邊,然後再走$2^$步,對這兩步中的最大邊取最大值即可;對於次大邊,如果這兩個模組內的最大邊相等,則我們用這兩個模組的次大邊更新;如果第一階段的最大邊$>$第二階段的最大邊,那麼最大邊在第一階段的次大邊與第二階段的最大邊中取最大值,不然則反之。

#include #include 

#include

#include

#include

using

namespace

std;

using ll = long

long

;const

int n = 1e5+10, m = 3e5+10

;struct

node

}edge[m];

intn, m, p[n];

int h[n], e[n*2], ne[n*2], w[n*2

], idx;

int f[n][18], g[n][18][2

], d[n];

bool

st[m];

void add(int a, int b, int

c)int find(int

x)void merge(int c[2], int a[2], int b[2

])void bfs(int

u) }}}

}int lca(int res, int x, int

y) }

if(x==y) return

x;

for(int i=17; i>=0; i--)

}merge(res, res, g[x][

0]);

merge(res, res, g[y][

0]);

return f[x][0];}

int main(void

) }

bfs(1);

int delta =int_max;

for(int i=0; i)

}cout

return0;

}

AcWing 356 次小生成樹

一道蠻經典的題目,隨手記錄下。題目描述 給定一張 n 個點 m 條邊的無向圖,求無向圖的嚴格次小生成樹。設最小生成樹的邊權之和為sum,嚴格次小生成樹就是指邊權之和大於sum的生成樹中最小的乙個。注意本題所求的次小生成樹是嚴格次小的 題解 先用kruskal求出給定圖的最小生成樹,再列舉沒有被選上的...

AcWing 356 次小生成樹(lca)

給定一張 n 個點 m 條邊的無向圖,求無向圖的嚴格次小生成樹。設最小生成樹的邊權之和為sum,嚴格次小生成樹就是指邊權之和大於sum的生成樹中最小的乙個。第一行包含兩個整數n和m。接下來m行,每行包含三個整數x,y,z,表示點x和點y之前存在一條邊,邊的權值為z。包含一行,僅乙個數,表示嚴格次小生...

最小生成樹 次小生成樹

一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 1.兩點之間的路徑是唯一的。2.邊數等於點數減一。3.連線任意兩點都會生成乙個環。對於乙個無向聯通圖g的子圖,如果它包含g的所有點,則它被稱為g的生成樹,而各邊權和最小的生成樹則被稱...