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