s 城現有兩座監獄,一共關押著 n 名罪犯,編號分別為 1 - n 。他們之間的關係自然也極不和諧。很多罪犯之間甚至積怨已久,如果客觀條件具備則隨時可能爆發衝突。我們用「怨氣值」(乙個正整數值)來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之間的積怨越多。如果兩名怨氣值為 c 的罪犯被關押在同一監獄,他們倆之間會發生摩擦,並造成影響力為 c 的衝突事件。
每年年末,警察局會將本年內監獄中的所有衝突事件按影響力從大到小排成乙個列表,然後上報到 s 城 z 市長那裡。公務繁忙的 z 市長只會去看列表中的第乙個事件的影響力,如果影響很壞,他就會考慮撤換警察局長。
在詳細考察了 n 名罪犯間的矛盾關係後,警察局長覺得壓力巨大。他準備將罪犯們在兩座監獄內重新分配,以求產生的衝突事件影響力都較小,從而保住自己的烏紗帽。假設只要處於同一監獄內的某兩個罪犯間有仇恨,那麼他們一定會在每年的某個時候發生摩擦。
那麼,應如何分配罪犯,才能使 z 市長看到的那個衝突事件的影響力最小?這個最小值是多少?
每行中兩個數之間用乙個空格隔開。第一行為兩個正整數 n,m分別表示罪犯的數目以及存在仇恨的罪犯對數。接下來的 m行每行為三個正整數 aj,bj,cj,表示 aj號和 bj號罪犯之間存在仇恨,其怨氣值為 cj。資料保證1共 1 行,為 z 市長看到的那個衝突事件的影響力。如果本年內監獄中未發生任何衝突事件,請輸出0
。
**:
1 #include 2 #include 3 #include 4 #include 56using
namespace
std;78
const
int n = 20010, m = 1e5 + 10;9
struct
it10
its[m];
13int
n, m;
14int
p[n];
15int
d[n];
1617
bool
cmp(it x, it y)
1821
22int find(int
x)23
2728
intmain()29;
37}3839 sort(its + 1, its + 1 +m, cmp);
4041
intres;
42for (int i = 1; i <= m + 1; i ++)
4350
else
5158
if (!d[its[i].b]) d[its[i].b] =its[i].a;
59else
6064}65
}6667 cout << res <68return0;
69 }
本題,因為說了有「邊權值」(我理解為矛盾值),所以要求出現矛盾情況下的最小邊權值顯然是需要排序的
那麼問題又來了,我們要按照什麼方法進行分配呢?
我們不妨這樣想:兩個人a,b有仇,那麼把他們放在一起顯然會打起來,那麼我們還不如把a與b的其他敵人放在一起,
因為這樣可能會出現「敵人的敵人就是朋友」的情況,恰好a與b的其他敵人之間沒有矛盾,那麼他們就可以放在同乙個集合中,反之b對a亦然。
那麼我們不妨這樣實現: 首先需要並查集初始化
(1)先把所有的矛盾關係按照矛盾值從大到小排一遍序,
(2)接下來每次操作取出乙個關係,看矛盾的兩個人x和y是否已經分配到同乙個集合中(並查集找父親即可),那麼還分如下兩種情況:
如果在一起那麼顯然會打起來(會出現矛盾),那麼直接輸出當前的邊權(矛盾值)即可(此時保證是最小矛盾值,因為已經排序了)
如果不在同一組,則按照「敵人的敵人就是朋友」的原則,把x與y的其他敵人分在同一組,y與x的其他敵人分在同一組
不斷進行以上操作最終可以得到答案
洛谷p1525 並查集
先將最大的犯罪都找出來然後將人員分組 假設兩人x,y 如果x 前面已經有過敵人了 那就將y合併到x的敵人裡去 y也是如此若有 將x合併到y的敵人去 如果x 和 y前面都沒有 那麼互相將彼此設為敵人 直到找到矛盾的 就是 xy有同乙個敵人 include include include using n...
並查集 洛谷P1525 關押罪犯
我以前學的是假的並查集 這個題目有很明顯的歸屬關係,可一用並查集搞一搞 普遍來說有兩種方法 1.權值並查集 2.拆點並查集 我們乙個乙個來 當然他們的共同條件就是要先把邊按權值遞減排序,不斷加入,直到無法避免矛盾,那麼直接輸出答案 權值並查集 這個很難解釋啊 我們定義如果x,y相連,那麼代表他們在不...
洛谷P1525 關押罪犯(種類並查集 貪心)
s城現有兩座監獄,一共關押著 n名罪犯,編號分別為1 n。他們之間的關係自然也極不和諧。很多罪犯之間甚至積怨已久,如果客觀條件具備則隨時可能爆發衝突。我們用 怨氣值 乙個正整數值 來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之間的積怨越多。如果兩名怨氣值為c 的罪犯被關押在同一監獄,他們...