洛谷P1967 貨車運輸

2021-09-26 01:35:28 字數 2092 閱讀 6286

首先說這道題的思路:存在多條路徑時求路徑最大權的最小值問題,可以利用生成樹的性質重建給出的圖,將多路徑轉化為一定最優的單一路徑,再在樹上求lca時統計權值來求出「路徑最大權的最小值」。

寫這份**的時候複習了幾個重要的知識點:

並查集在寫生成樹時,經常會用到並查集。

ll find

(ll x)

並查集的**非常簡單,需要注意的是,在合併時,語句為:

f[

find

(x)]

=find

(y);

而不是:

f[x]

=find

(y);

下面的寫法會漏合併x所在的集合的其他點 (我在這裡卡了是真的丟人)

lca這道題中的lca與一般的lca大同小異,只是在求2

i2^i

2i級父節點時一起將到2

i2^i

2i級父節點的「路徑最大權的最小值」一起求出來,在倍增求lca時也加入統計「路徑最大權的最小值」的**即可。同時,由於這道題可能給出森林,因此需要將每個點都作為根來dfs,同時加入特判來判定某個點是否已經屬於某棵已知的樹。

void

dfs(ll k,ll fa)

for(

int i=head[k]

;i;i=l[i]

.n)}

ll lca

(ll u,ll p)

if(u==p)

return ans;

for(

int i=

19;i>=

0;i--)}

ans=

min(ans,

min(w[u][0

],w[p][0

]));

//統計「路徑最大權的最小值」

return ans;

}

其他重要操作還有前向星生成樹,不過這些較為簡單,就不再贅述,**見下方即可。

ac**:

#include

#include

#define ll long long

using namespace std;

const

int maxn=

1e5+5;

ll n,m,x,y,z,q;

ll b[maxn]

;//並查集

ll head[maxn]

,ecnt=1;

//前向星

ll v[maxn]

,f[maxn][20

],d[maxn]

;//lca

ll w[maxn][20

];//lca中到父節點的最小邊權

struct edgee[maxn]

;struct listl[maxn]

;bool cmp

(edge a,edge b)

ll find

(ll x)

void

swap

(int

&a,int

&b)void

add(ll a,ll b,ll c)

void

scs()}

}void

dfs(ll k,ll fa)

for(

int i=head[k]

;i;i=l[i]

.n)}

ll lca

(ll u,ll p)

if(u==p)

return ans;

for(

int i=

19;i>=

0;i--)}

ans=

min(ans,

min(w[u][0

],w[p][0

]));

return ans;

}/*void out()

}*/int

main()

return0;

}

以及,善用注釋!

洛谷 P1967 貨車運輸

a 國有 n 座城市,編號從 1 到 n,城市之間有 m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 q 輛貨車在運輸貨物,司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。輸入檔名為 truck.in。輸入檔案第一行有兩個用乙個空格隔開的整數 n,m,表示 a 國有 ...

洛谷 P1967 貨車運輸

題目描述 a 國有 n 座城市,編號從 1 到 n,城市之間有 m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 q 輛貨車在運輸貨物,司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。輸入輸出格式 輸入格式 輸入檔名為 truck.in。輸入檔案第一行有兩個用乙個空格隔...

貨車運輸 洛谷p1967

解法一 30分 直接跑spfa,求最大瓶頸路。include include include define f i,l,r for i l i r i using namespace std const int maxn 10005,maxm 50005,inf 100000000 struct e...