最小瓶頸路

2021-09-29 17:19:51 字數 3934 閱讀 8878

在一張無向圖中,詢問乙個點對(u,v),找出從u到v的一條簡單路徑,使路徑上所有邊中最大值最小。

應用:次小生成樹

給定一張無向圖,求出一棵生成樹,其所有邊的權值之和僅次於最小生成樹的權值之和(如果有多個最小生成樹的話次小生成樹就是最小生成樹)。

思路:先求出最小生成樹。列舉所有樹外的邊加入最小生成樹,則一定會構成乙個環,此時需要在這個環中任意斷開一條邊,使其依然成為一棵樹。為了盡量使權值之和最小,我們需要斷開樹上加入的邊的兩端點之間權值最大的邊,則問題變為最小瓶頸路問題,可以用lca解決

即題目只需要查詢一對st到ed

例題:p1396 營救

題意:給n個點m條邊的無向圖

給st和ed,找一條從st至ed的路徑,使得經過的邊權最大值最小。

輸出路徑的最大邊權

思路:1.二分最大值,check為判斷只走小於等於mid的邊能否從st到達ed

2.kruksal,從小到大合併邊,當st和ed在同一連通塊的時候答案為當前合併的邊的邊權

code:

**在這

即題目多次給出st和ed,需要查詢多次。

例題:p2245 星際導航

題意:給n個點m條邊的無向圖,

q組詢問,給st和ed,找一條從st至ed的路徑,使得經過的邊權最大值最小。

輸出路徑的最大邊權

如果st無法到達ed輸出impossible

思路:1.最小生成樹+lca

求出最小生成樹之後求st到ed之間的最大值,用lca來求最值

結論很顯然就不證明了

2.kruskal重構樹

kruskla重構樹的基礎應用

ps:題目可能有多個連通塊

code1:

最小生成樹+lca

**裡面lca用邊權樹剖實現的

#include

using

namespace std;

//#define int long long

const

int maxm=

4e5+5;

struct nodee[maxm]

;struct edgeee[maxm]

;int num;

int head[maxm]

,nt[maxm]

,to[maxm]

,w[maxm]

,cnt;

int sz[maxm]

,son[maxm]

,top[maxm]

,d[maxm]

,id[maxm]

,fa[maxm]

,rk[maxm]

,idx;

int a[maxm<<2]

;int pre[maxm]

;int mark[maxm]

;int v[maxm]

;int n,m;

void

init()

cnt=1;

num=0;

}bool

cmp(node a,node b)

void

add(

int x,

int y)

intffind

(int x)

void

dfs1

(int x)}}

void

dfs2

(int x,

int tp)

for(

int i=head[x]

;i;i=nt[i])}

void

pushup

(int node)

void

build

(int l,

int r,

int node)

int mid=

(l+r)/2

;build

(l,mid,node*2)

;build

(mid+

1,r,node*2+

1);pushup

(node);}

intask

(int st,

int ed,

int l,

int r,

int node)

int mid=

(l+r)/2

;int ans=0;

if(st<=mid)

if(ed>=mid+1)

return ans;

}void

kruskal()

;add

(e[i]

.a,e[i]

.b);

add(e[i]

.b,e[i]

.a);}}

for(

int i=

1;i<=n;i++)}

for(

int i=

1;i<=num;i++

)build(1

,n,1);

//建樹

}int

lca(

int x,

int y)

if(d[x]

>d[y]

)swap

(x,y)

; ans=

max(ans,

ask(id[son[x]

],id[y],1

,n,1))

;return ans;

}signed

main()

kruskal()

;int q;

cin>>q;

while

(q--

)else

}return0;

}

code2:

kruskal重構樹

注意陣列別開小了

#include

using

namespace std;

//#define int long long

const

int maxm=

4e5+5;

struct nodee[maxm]

;int head[maxm]

,nt[maxm]

,to[maxm]

,cnt;

int sz[maxm]

,son[maxm]

,fa[maxm]

,top[maxm]

,d[maxm]

;int pre[maxm]

;int mark[maxm]

;int val[maxm]

;int n,m;

bool

cmp(node a,node b)

void

init()

cnt=1;

}void

add(

int x,

int y)

void

dfs1

(int x)}}

void

dfs2

(int x,

int tp)

for(

int i=head[x]

;i;i=nt[i])}

intffind

(int x)

void

kruskal()

}for

(int i=

1;i<=n;i++)}

}int

lca(

int x,

int y)

if(d[x]

>d[y]

)swap

(x,y)

;return x;

}signed

main()

kruskal()

;int q;

cin>>q;

while

(q--

)else

}return0;

}

最小瓶頸路

題目 uva 534 題目大意 有兩隻青蛙,在兩塊不同的石頭上,有乙隻想要去拜訪另乙隻,要求通過它石頭進行跳躍然後在一起呀在一起,可想而知,由於石頭有很多,他們中間的路徑也有很多,現在要求求乙個長度 從每條路徑裡面挑出那步跨越最大的,然後從這些跨越最大的裡面挑出最小的。分析 flody 的改版 in...

P1396 營救 最小瓶頸路

這個題貌似時最小瓶頸路的前身,單次離線查詢。思路 1.最小生成樹kru skal kruskal kruska l,當s,t s,ts,t連通時的對應邊權值為答案。include using namespace std typedef long long ll const int n 1e4 5,m...

UVa 11354 邦德(最小瓶頸路 LCA)

題意 有n個城市m條道路,每條道路有乙個危險係數。先在有若干個詢問,要求找到一條從s到t的路,使得途徑所有邊的最大危險係數最小。思路 最小瓶頸路肯定是在最小生成樹上的。所有先求最小生成樹。然後將它轉化成有根樹,讓fa i 和cost i 分別表示結點i的父親編號和它與父親之間的邊權l i 表示結點i...