美麗的路徑 並查集,搜尋,二分

2021-10-22 17:24:29 字數 1488 閱讀 1120

鏈結

知識點

並查集,搜尋,二分

思路

第k 2+

1\frac+1

2k​+

1小的數,那就是中位數,需要注意的是題目中沒有說要是最短路,所以為了讓美麗值最大,可以讓這條路徑在兩個權值大的點之間反覆行走。

那麼可以發現會有很多個美麗值,那麼可以對答案進行二分,去找最大的那個。

首先是判斷起點到終點之間是否聯通,這個用搜尋,或者並查集都可以。

當可以連通的時候,二分。設當前美麗值為x,路徑的美麗值就是此路徑上的所有點的點權中第⌊k/2+1⌋小的點權,等價於大於等於x的點的數量大於等於路徑中所有點的一半。

換句話說,如果發現大於等於x的點的數量大於等於路徑中所有點的一半,說明此時的x值取小了,l=m

+1

l=m+1

l=m+

1,否則r=m

−1

r=m-1

r=m−1.

如何判斷大於等於x的點的數量大於等於路徑中所有點數量的一半?

設大於等於x的點為1點,否則為0點。

當有兩個1點連續時,可以不斷來回走,必然大於一半。

只有當10101010交錯出現時,且1的個數大於0的個數,必然大於一半。

容易發現只有0101010交錯出現時,且開始點和結束點都為0,才會小於。

**

#include

#include

using

namespace std;

const

int maxn =

200005

;typedef

long

long ll;

int a[maxn]

;int vis[maxn]

;int fa[maxn]

;vector<

int> g[maxn]

;int t,n,m,s,t;

int ans =0;

bool flag =

false

;int

find

(int x)

void

dfs(

int u,

int x)

}void

dfs2

(int u,

int x)

}int

check

(int x)

intmain()

int u,v;

for(

int i =

1;i <= m;i++)if

(find

(s)==

find

(t))

cout<}else

cout<<

"no"

<}return0;

}

關押罪犯 並查集 二分

s 城現有兩座監獄,一共關押著n 名罪犯,編號分別為1 n。他們之間的關係自然也極不和諧。很多罪犯之間甚至積怨已久,如果客觀條件具備則隨時可能爆發衝突。我們用 怨氣值 乙個正整數值 來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之間的積怨越多。如果兩名怨氣值為c 的罪犯被關押在同一監獄,他...

擴散(二分答案 並查集)

乙個點每過乙個單位時間就會向四個方向擴散乙個距離,兩個點a b連通,記作e a,b 當且僅當a b的擴散區域有公共部分。連通塊的定義是塊內的任意兩個點u v都必定存在路徑e u,a0 e a0,a1 e ak,v 給定平面上的n給點,問最早什麼時刻它們形成乙個連通塊。我們可以二分答案,然後對於每個時...

poj3657 二分 並查集

二分哪一次操作是最後一次正確的操作 1即為錯誤操作。把最小值相同的詢問確定下來,可以得到乙個最小的集合,再更新這個集合的所屬,若有衝突就說明此操作有問題。include include include define maxd 1000010 define maxq 25010 using names...