原文必點
原題鏈結
給定一張\(n\) 個點$ m $條邊的無向圖,求無向圖的嚴格次小生成樹。
設最小生成樹的邊權之和為\(sum\),嚴格次小生成樹就是指邊權之和大於\(sum\)的生成樹中最小的乙個。
輸入格式
第一行包含兩個整數\(n\)和\(m\)。
接下來\(m\)行,每行包含三個整數\(x,y,z\),表示點\(x\)和點\(y\)之前存在一條邊,邊的權值為\(z\)。
輸出格式
包含一行,僅乙個數,表示嚴格次小生成樹的邊權和。(資料保證必定存在嚴格次小生成樹)
資料範圍
\[n \le 10^5 \\\\
m \le 3*10^5
\]輸入樣例:
5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
輸出樣例:11
題意理解
要你構造一棵\(n\)個節點的嚴格次小生成樹.
演算法解析
分析條件
題目中給出的關鍵點,就是嚴格和次小.
什麼是嚴格
就是題目強制要求嚴格單調性,不可以有\(=\)號的出現.
什麼是次小
我們應該都知道,最小生成樹,它要求邊集合的邊總和最小,那麼次小生成樹,要求邊集合的邊總和只比最小生成樹邊集合權值大.
總結性質
有至少乙個(嚴格)次小生成樹,和最小生成樹之間只有一條邊的差異。和真理只有一點差異,那就是出題人毒瘤
我們來粗略證明一下.(強行偽證)
我們知道最小生成樹,是由\(n-1\)條構成的.
那麼其他的\(m-n+1\)就是多餘邊.
假如說我們把一條多餘邊\((x,y,z)\),加入到了最小生成樹中,那麼一定會在\((x,y)\)之間的路徑上形成乙個環.
那麼這個環上面,最大的邊稱之為
\[val_1
\]次大的邊,稱之為
\[val_2
\]而且為了保證嚴格這個單調性質,我們必須設
\[val_1>val_2 \quad 最大的邊一定大於次大的邊
\]接下來,我們就需要好好分析一下這條多餘邊了.
我們知道多餘邊,替換任何一條樹上的一條邊,都會使得最小生成樹,不再最小
為什麼?
因為最小生成樹上的每一條邊,一定是滿足貪心性質下的最小的邊.為什麼啊?相信你的直覺啊
這個證明,我們使用的克魯斯卡爾演算法,已經告訴我們為什麼.真相只有乙個,我懶了
總而言之,言而總之,我們現在知道了這條多餘邊的加入.,一定會產生非最小生成樹.
我們不妨令
\[ans=最小生成樹邊權之和
\]假如說我們將多餘邊,替換掉最大權值邊.
\[val_1 ==> z \\\
此時我們發現當前生成樹 w=ans+z-val_1 \\\\
w=最小生成邊權之和+加上多餘邊-最大權值邊
\]這一輪替換,我們可以認為這棵生成樹有潛力成為次小生成樹.
然後,我們發現,換一換次大邊,也是可以的.
我們將多餘邊,強行替換掉次大權值邊.
\[val_2 ==> z \\\\
此時當前生成樹 w=ans+z-val_2 \\\\
w=最小生成樹之和+加入多餘邊-次大權值邊
\]現在所有的候選生成樹都出來了,但是我們面臨乙個非常嚴重的問題.
我們如何快速計算,一條路徑上的最大邊,和次大邊.
動態規劃
我們可以當前需要知道的狀態,無非就是兩個.
一條路徑上的最大邊
一條路徑上的嚴格次大邊
所以說,我們不妨就按照倍增陣列的思路,去製造兩個新陣列.
最大邊陣列
嚴格次大邊陣列
\[f[x][k]=f[fa[x][k-1]][k-1]
\]這是我們非常熟悉的lca倍增陣列.
然後咱們現在其實,手上掌握的最有力的性質,就是最值性質.
我們假設一條路徑是由三段構造而成.
是三段,不是就三個點.
\[a=>c,c=>b,b=>a
\]我們發現
\[a=>b的最大值其實等於 \\\\
max(a=>c最大值,b=>c最大值)
\]這就是區間最值性質.
不過嚴格次大邊,就比較麻煩了,不慌,咱們慢慢畫圖來.
為了下面簡述方面,我們設定一下變數.
\[a=>c上最大邊權為val_ \quad 次大邊權為v_ \\\\
c=>b上最大邊權為val_ \quad 次大邊權為v_ \\\\
a=>b上最大邊權為val_ \quad 次大邊權為v_ \\\\
\]巧計一下,val字母多,所以是最大邊權,v字母少,所以是次大邊權.
我們分類討論一下,三種情況.
①第一段最大值=第二段最大值
\[val_=val_
\]我們發現兩段居然最大值一樣.
次大邊權就只能
\[v_=max(v_,v_)
\]②第一段最大值<第二段最大值.
那麼此時,次大邊權是可以取第一段最大值.
因為此時總段的最大值,一定是第二段最大值.
\[val_=val_ \\\\
因此v_可以=val_
\]綜上所述,我們總結下來就是.
\[v_=max(val_,v_)
\]③第一段最大值>第二段最大值.
那麼此時,次大邊權是可以取第二段最大值.
因為此時總段的最大值,一定是第一段最大值.
\[val_=val_ \\\\
因此v_可以=val_
\]同樣,總結一下.
\[v_=max(val_,v_)
\]然後我們將\(a,b,c\)具體化一下.
a其實就是起始節點.
c其實就是a跳躍了\(2^\)格節點.
b其實就是a跳躍了\(2^\)格節點.
**解析
#include using namespace std;
#define inf 1e16
const int n=1e5+200;
const int m=6*1e5+300;
int head[m],edge[m],next[m],ver[m],tot,fa[m],n,m,father[n][32],deep[n];
long long dp[2][n][32],val1,val2,ans_max,ans;
struct node
s[m];
int cmp(node a,node b)
else}}
}}inline void update2(int x)
inline void update(int x, int t)
inline void lca(int x, int y)
if(x==y)
return;
for(int t=(int)log2(deep[x]); t>=0; t--)
}update(x,0),update(y,0);
}} g1;
int main()
g1.kruskal();
g1.bfs(1);
ans_max=inf;
for(int i=1; i<=m; i++)
}printf("%lld\n",ans_max);
return 0;
}
BJWC2010 嚴格次小生成樹
板子題 先kruskal得到最小生成樹,再列舉未加進生成樹中的邊i,該邊i和生成樹樹形成了乙個環,選擇這個環上最大的不等於i的權值的邊去掉就得到乙個新的樹,所有這樣得到的樹權值之和即為次小生成樹。求環上最大邊可以用倍增或者樹鏈剖分,由於最大邊可能和才加上去的邊相等,所以還要維護乙個次大邊 inclu...
P4180 嚴格次小生成樹 BJWC2010
題目鏈結 當時在暑假早就講了這道題了,只不過我現在才做了這道題。題解 我們要求次小生成樹的話,考慮先把最小生成樹求出來,因為如果我們用求最小生成樹的話,邊早已經從大到小排序好了,所以次小生成樹的就是替換最小生成樹上的一條邊所得。那麼考慮如何來替換那一條邊,要保證嚴格次小,那麼我們需要替換掉最小生成樹...
P4180 BJWC2010 嚴格次小生成樹
題目 最小生成樹都會吧?不會的戳這裡 接下來我們用lca求每一條非樹邊在樹上環的最大邊權和次大邊權,然後求乙個min s mx v,s mx2 v,mn 就可以了,注意如果mx v,第一項不比較.code include include include include include include...