倍增法求lca:
求小資料次小生成樹:
給定一張 n 個點 m 條邊的無向圖,求無向圖的嚴格次小生成樹。
設最小生成樹的邊權之和為sum,嚴格次小生成樹就是指邊權之和大於sum的生成樹中最小的乙個。
輸入格式
第一行包含兩個整數n和m。
接下來m行,每行包含三個整數x,y,z,表示點x和點y之前存在一條邊,邊的權值為z。
輸出格式
包含一行,僅乙個數,表示嚴格次小生成樹的邊權和。(資料保證必定存在嚴格次小生成樹)
資料範圍
n≤1e5,m≤3∗1e5
輸入樣例:
5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
輸出樣例:
11
思路:這題的n有1e5,所以就不能像以前一樣用dfs求沿路上的邊的最大值和次大值。這裡我用倍增法求lca,順便記錄沿路上的最大值和次大值。lca的複雜度就比較小,可以搞這題。求次小生成樹的原理還是和之前差不多的,就是判斷每條非樹邊能不能替代原本樹上的邊。
#include#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int n=1e5+10,m=6e5+10;
struct ddq[m];
int n,m;
int first[n],ne[m],v[m],w[m],num_edge=0;
//f有兩個作用,乙個是在kruskal中建最小生成樹
//乙個是記錄每個人的直屬父親
int f[n],depth[n];
//dist1記錄從某個點跳2^i層的路徑中的最長邊
//dist1記錄從某個點跳2^i層的路徑中的次長邊
//st記錄從某個點跳2^i層所到達的點
int dist1[n][20],dist2[n][20],st[n][20];
//temp用於尋找lca中記錄下所有途經的邊,方便找到最大值次大值
int temp[m],cnt;
int qq[n];
bool cmp(dd x,dd y)
//找到lca,並記錄沿路的dist1和dist2
if(x!=y)
temp[++cnt]=dist1[x][0];
temp[++cnt]=dist1[y][0];
}//找一路上的最長邊和次長邊
int d1=-inf,d2=-inf;
for(int i = 1; i <= cnt; i++)
//printf("%d %d %d\n",z,d1,d2);
//這條邊可以代替最長邊
if(z>d1)return z-d1;
//這條邊可以代替次長邊
if(z>d2)return z-d2;
//啥都代替不了
return inf;
}int main()
次小生成樹(lca)
題目描述 原題來自 beijing 2010 組隊賽 給定一張 n個點 m條邊的無向圖,求無向圖的嚴格次小生成樹。設最小生成樹的邊權之和為 sum,嚴格次小生成樹就是指邊權之和大於 sum 的生成樹中最小的乙個。輸入格式 第一行包含兩個整數 n 和 m,表示無向圖的點數與邊數 接下來 m行,每行三個...
次小生成樹(LCA )
給定一張 n 個點 m 條邊的無向圖,求無向圖的嚴格次小生成樹。設最小生成樹的邊權之和為sum,嚴格次小生成樹就是指邊權之和大於sum的生成樹中最小的乙個。輸入格式 第一行包含兩個整數n和m。接下來m行,每行包含三個整數x,y,z,表示點x和點y之前存在一條邊,邊的權值為z。輸出格式 包含一行,僅乙...
次小生成樹 倍增 LCA
給乙個n個點m條邊 n 100000,m 300000 的無向圖,求它的嚴格次小生成樹。資料範圍很大,o n 2 的演算法顯然是不行的。由於最小生成樹是一棵樹,求任意兩點路徑上的最大 次大邊就成為了經典的lca問題。因此,我們得到了下面的演算法 1 把邊按權值從小到大排序,時間複雜度為o mlogm...