【問題描述】
小c最近學了很多最小生成樹的演算法,prim演算法、kurskal演算法、消圈演算法等等。
正當小c洋洋得意之時,小p又來潑小c冷水了。小p說,讓小c求出乙個無向圖的次小生成樹,而且這個次小生成樹還得是嚴格次小的,也就是說:如果最小生成樹選擇的邊集是em,嚴格次小生成樹選擇的邊集是es,那麼需要滿足:(value(e)表示邊e的權值)
這下小c蒙了,他找到了你,希望你幫他解決這個問題。
【輸入格式】
第一行包含兩個整數n 和m,表示無向圖的點數與邊數。 接下來 m行,每行 3個數x y z 表示,點x和點y之間有一條邊,邊的權值為z。
【輸出格式】
包含一行,僅乙個數,表示嚴格次小生成樹的邊權和。(資料保證必定存在嚴格次小生成樹)
【輸入樣例】 56
1211
3224
3354
3434
56【輸出樣例】
11 【資料範圍】
資料中無向圖無自環;
50% 的資料n≤2
000 m≤3
000;
80% 的資料n≤50
000 m≤100
000;
100% 的資料n≤100
000 m≤300
000 ,邊權值非負且不超過 10^9 。
#include
#include
#include
#include
#include
#include
#define maxn 100005
#define inf 11111111111111111
using
namespace
std;
struct data
;int n,m,x,y,z;
long
long oo=0,ans=inf;
int fa[maxn],ha[maxn],dep[maxn]=,dist[maxn]=;
vector
g;vector
p[maxn],q[maxn];
bool vis[300005]=;
void clear() //清空
int find(int x) //查詢
void union(int x,int y) //合併
bool check(int x,int y) //檢查
int getmax(int x,int y,int z)
bool cmp(data xx,data yy)
}void ****(int x,int y,int z) //x,x的父親,x的層數
}int main()
); }
clear();
sort(g.begin(),g.end(),cmp);
task();
****(1,1,1); //(1,1的父親,層數)
for(int i=0;iif(!vis[i])
ans=min(ans,oo+g[i].l-getmax(g[i].a,g[i].b,g[i].l));
cout
0;}
BJOI2010 嚴格次小生成樹
題目鏈結 乙個嚴格次小生成樹的模板題。看到次小生成樹,我們有乙個很直觀的想法就是先構造出來最小生成樹,然後將這個最小生成樹上面最大的一條邊替換成和它值最相近而且比他大的邊。那麼首先就是用kruskal演算法算出來最小生成樹,我們稱在這個最小生成樹上面的邊為樹邊 打上標記 不在的邊為非樹邊。之後就是用...
嚴格次小生成樹
顧名思義。生成樹,邊權和嚴格小於最小生成樹 一定和最小生成樹有關係。實際上,有 結論1 嚴格次小生成樹只在最小生成樹上改動一條邊 證明 改動一條邊有意義的話,必然改完這條邊,總和變大。那麼這至少是嚴格次小生成樹的最大值。再改一條也沒有意義。結論2 改動的那條邊w,一定是新加入的那條邊覆蓋的樹鏈的最大...
總結 嚴格 次小生成樹
首先需要了解什麼是最小生成樹,還要知道什麼是倍增 求lca 上面的東西如果了解了,就可以開始進入學習的路途了 用不是最小生成樹上的邊去更新答案.對於每乙個倍增跳上去的,要維護兩個東西 我們考慮一下對於每一條邊 不在最小生成樹上 如果要把它加入答案,如何更新?mst 路徑最大值 邊權.然後這個東西就可...