HYSBZ 1977 次小生成樹 Tree

2021-09-27 09:53:31 字數 1750 閱讀 3050

題意:

給定乙個有 n 個點、m 條邊的無向帶權圖,求嚴格次小生成樹。(n <= 1e5, m <= 3e5)

解題思路:

求非嚴格次小生成樹時,替換路徑上的最大邊,加入的邊權可能與其相等,故倍增時多維護乙個路徑上嚴格的次大值即可。

#include

using

namespace std;

typedef

long

long ll;

typedef pair<

int,

int> pii;

#define pb push_back

#define sz(a) ((int)a.size())

#define mem(a, b) memset(a, b, sizeof a)

#define lson (rt << 1)

#define rson (rt << 1 | 1)

#define gmid (l + r >> 1)

const

int maxn =

3e5+5;

const

int maxm =

6e6+5;

const

int mod =

1e9+7;

const

int inf =

0x3f3f3f3f

;vector g[maxn]

;struct edge

} ei[maxn]

;int pre[maxn]

, dep[maxn]

, fa[maxn][21

];int mx[maxn][21

], mx2[maxn][21

];int n, m, p;

intfin

(int x)

ll kruskal()

), g[v].pb

();}

else ei[

++p]

= ei[i];}

return ret;

}void

dfs(

int u,

int f)

dfs(v, u);}

}void

change

(int

&ret1,

int&ret2,

int u,

int i)

pii getmax

(int u,

int v)}if

(u == v)

return

;for

(int i =

20; i >=0;

--i)

}change

(ret1, ret2, u,0)

;change

(ret1, ret2, v,0)

;return;}

intmain()

ll ret =

kruskal()

, ret2 =

1ll<<62;

mem(mx[1]

,-1)

,mem

(mx2[1]

,-1)

;dfs(1

,0);

for(

int i =

1; i <= p;

++i)

printf

("%lld\n"

, ret2)

;return0;

}

BZOJ 1977 次小生成樹

傳送門 求嚴格次小生成樹 權值和嚴格小於最小生成樹 和無限制的次小生成樹一樣,唯一不同的是,嚴格小於,只需要將刪除非樹邊連線的兩點樹鏈上的最長邊改為刪除1.如果最長邊不等於該邊,就直接計算2.如果等於,就用次長邊計算。在最小生成樹上倍增即可。includeusing namespace std na...

BZOJ 1977 嚴格次小生成樹

題目鏈結 題意 求乙個圖的嚴格次小生成樹,n 100000,m 300000,邊權非負且 1e9 思路 按照正常次小生成樹思路,先生成一顆最小生成樹,並記錄任意兩點路徑上的最長邊,然後列舉非最小樹邊來求得答案,但現在要求的是嚴格次小生成樹所以我們還得知道兩點路徑上的嚴格次長邊 我們考慮使用lca維護...

BZOJ 1977 次小生成樹(最近公共祖先)

題意 求一棵樹的嚴格次小生成樹,即權值嚴格大於最小生成樹且權值最小的生成樹。思路 若現在已經得到了最小生成樹,那麼若 新增一條邊e,就會得到乙個環,我們只需要去掉環上權值小於e且最大的一條邊就會得到另一棵較優的生成樹。因此,只需要列舉不在生成樹上的邊,計算將其添 加到最小生成樹中得到的新生成樹的權值...