顧名思義。
生成樹,邊權和嚴格小於最小生成樹
一定和最小生成樹有關係。
實際上,有
結論1:嚴格次小生成樹只在最小生成樹上改動一條邊
證明:改動一條邊有意義的話,必然改完這條邊,總和變大。
那麼這至少是嚴格次小生成樹的最大值。再改一條也沒有意義。
結論2:改動的那條邊w,一定是新加入的那條邊覆蓋的樹鏈的最大值或者嚴格次大值。
證明:w比最大值大的話,一定扔掉這個最大值
相等的話,一定扔掉嚴格次大值。
如果不存在嚴格次大值,那麼不可能。也符合「嚴格」的題意。
kruscal跑mst
列舉剩下沒有加入的邊,要求出這條鏈上的最大值和嚴格次大值
可以倍增,樹剖,lct等等。
倍增顯然最優。
【模板】嚴格次小生成樹[bjwc2010]
#include#define il inline#define reg register int
#define numb (ch^'0')
#define int long long
using
namespace
std;
typedef
long
long
ll;il
void rd(int &x)
namespace
miracle
}bian[m];
intff[n];
int fin(int
x)int fa[n][20],mx[n][20],cmx[n][20
];ll sum;
struct
edgee[
2*n];
inthd[n],cnt;
void add(int x,int y,int
z)int
dep[n];
ll ans;
void dfs(int x,intd)}
int query(int x,int y,ll z)
}if(x==y)
for(reg j=19;j>=0;--j)
}int j=0
;
if(mx[x][j]!=z) big=max(big,mx[x][j]);
else big=max(big,cmx[x][j]);
if(mx[y][j]!=z) big=max(big,mx[y][j]);
else big=max(big,cmx[y][j]);
return z-big;
}int
main()
for(reg i=1;i<=n;++i) ff[i]=i;
sort(bian+1,bian+m+1
);
for(reg i=1;i<=m;++i)
}//cout<<" sum "; dfs(
1,1);
for(reg j=1;j<=19;++j)
}ans=0x3f3f3f3f3f3f3f3f
;
for(reg i=1;i<=m;++i)
}printf(
"%lld
",ans);
return0;
}}signed main()
/*author: *miracle*
date: 2018/12/19 14:36:23
*/
總結 嚴格 次小生成樹
首先需要了解什麼是最小生成樹,還要知道什麼是倍增 求lca 上面的東西如果了解了,就可以開始進入學習的路途了 用不是最小生成樹上的邊去更新答案.對於每乙個倍增跳上去的,要維護兩個東西 我們考慮一下對於每一條邊 不在最小生成樹上 如果要把它加入答案,如何更新?mst 路徑最大值 邊權.然後這個東西就可...
嚴格次小生成樹學習筆記
嚴格次小生成樹,顧名思義,就是在聯通圖上選擇一些邊構成一棵樹,使這棵樹邊權和嚴格次小。要求嚴格次小生成樹,我們就要先求出最小生成樹 prim 和 kruskal 等演算法都可以,我用的是 kruskal 在求最小生成樹的過程中,還要給每條使用過的邊打乙個標記,如下 inline void krusk...
瘋子的演算法總結11 次小生成樹 嚴格次小生成樹
首先,我這一題的思路是倍增lca kruskal 首先,kruskal求最小生成樹 不會的戳這裡 求次小生成樹 倍增 lca 關鍵在於次小生成樹怎麼求 問自己一些問題 怎麼求不嚴格次小生成樹 不嚴格次小生成樹為什麼不嚴格 方法每次選擇u v之間的邊,前提是最小生成樹上不存在的邊,添邊之後刪去較短邊,...