希望更好的閱讀體驗?點這裡
貝蒂是一頭奶牛,一直快樂的生活在約翰的奶牛農場裡,奶牛農場裡有很多牧場,牧場與牧場之間有道路連線(道路是雙向的),經過每一條道路都需要支付一定的費用,如果貝蒂從乙個牧場到另乙個牧場時(中間可能會經過其他牧場),在這條路徑的每一條道路上支付的費用都差不多,則貝蒂感到很快樂,反之貝蒂經過的路徑上花費最高費用的道路和最低費用的道路差值越大,貝蒂越生氣,現在給定兩個牧場,請你幫忙找到盡可能讓貝蒂快樂的路徑。
第一行有2個正整數 n
nn (1
2001 < n \le 200
1200)和 m
mm (m
≤1000
m \le 1000
m≤1000
),表示約翰的農場裡有 n
nn 個牧場和 m
mm 條道路。 接下來的 m
mm 行,每行 3
33 個數,分別表示道路的起點牧場和終點牧場,以及費用(費用 ≤
1000000
\le 1000000
≤10000
00) 然後是乙個正整數q(q
<
11q < 11
q<11
),表示給定的起點和終點的組數。 接下來 q
qq 行每行有 2
22 個正整數 s,e
s,es,
e , 表示起點牧場和終點牧場。
對每個輸入給定的起點和終點,輸出 1
11 行,輸出乙個非負整數表示能讓貝蒂感到最快樂的那條路線上費用最高的道路和費用最低的道路之間費用之差。如果無論如何從起點都到不了終點,則輸出 −1-1
−1。首先看到題目會想到用最短路或bfs做,但這麼做是不對的,因為最短路不能確定最小的差值,有可能按照dijkstra、spfa或floyd做完後求的不是最小的差。那麼應該怎麼做?
因為差最小,所以應該盡可能讓費用最大值小,這樣相對的差值就小一點。因此可以想到把邊從小到大排序,再用並查集維護兩個點的連通性。這種做法跟kruskal的區別是它只維護從 s
ss 到 e
ee 的包含s
ss 和 e
ee 的生成樹。
注:如果加入了一條邊與 s
ss 到 e
ee 的路徑無關也是沒有關係的,因為道路是雙向的,可以從無關的那條邊走回原起點。
既然這樣,我們就可以暴力列舉第一條邊,在迴圈內部列舉其他邊(注意不能重複),如果兩個點沒有被加入集合,就加進去,如果加邊後 s
ss 與 e
ee 在同一連通塊內就直接退出,最後答案為最後一次加的邊的費用與第一條邊的費用的差(已經排序過了就可以直接這麼做)。
沒想到用並查集就不會做這道題目……還是很有思維難度的。#include
#include
#define min(a,b) ((a)<(b)?(a):(b))
struct edgee[
1003];
bool
cmp(edge x,edge y)
int n,m,q,fa[
203]
;int
find
(int x)
void
union
(int x,
int y)
//標準並查集寫法
intmain()
if(j<=m) ans=
min(ans,e[j]
.dis-e[i]
.dis)
;//j>m說明s與e不連通,不能更新答案
}printf
("%d\n"
,ans==
1<<30?
-1:ans);}
return0;
}
並查集 並查集
本文參考了 挑戰程式設計競賽 和jennica的github題解 陣列版 int parent max n int rank max n void init int n int find int x else void union int x,int y else 結構體版 struct node ...
並查集入門(普通並查集 帶刪除並查集 關係並查集)
什麼是並查集?通俗易懂的並查集詳解 普通並查集 基礎並查集 例題 題解 how many tables problem description lh boy無聊的時候很喜歡數螞蟻,而且,還給每乙隻小螞蟻編號,通過他長期的觀察和記錄,發現編號為i的螞蟻會和編號為j的螞蟻在一起。現在問題來了,他現在只有...
並查集,帶權並查集
題意 ignatius過生日,客人來到,他想知道他需要準備多少張桌子。然而一張桌子上面只能坐上相互熟悉的人,其中熟悉可定義成為a與b認識,b與c認識,我們就說a,b,c相互熟悉 例如a與b熟悉and b與c熟悉,d與e熟悉,此時至少需要兩張桌子。輸入 t表示樣例個數,n表示朋友個數,朋友從1到n編號...