並查集補集做法 codevs 1069 關押罪犯

1069 關押罪犯

 

2010年NOIP全國聯賽提升組ios

 時間限制: 1 s
 空間限制: 128000 KB
 題目等級 : 鑽石 Diamond
 
 
 
題目描述  Description

S 城現有兩座監獄,一共關押着N 名罪犯,編號分別爲1~N。他們之間的關係天然也極flask

不和諧。不少罪犯之間甚至積怨已久,若是客觀條件具有則隨時可能爆發衝突。咱們用「怨app

氣值」(一個正整數值)來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之spa

間的積怨越多。若是兩名怨氣值爲c 的罪犯被關押在同一監獄,他們倆之間會發生摩擦,並code

形成影響力爲c 的衝突事件。blog

每一年年底,警察局會將本年內監獄中的全部衝突事件按影響力從大到小排成一個列表,排序

而後上報到S 城Z 市長那裏。公務繁忙的Z 市長只會去看列表中的第一個事件的影響力,事件

若是影響很壞,他就會考慮撤換警察局長。ip

在詳細考察了N 名罪犯間的矛盾關係後,警察局長以爲壓力巨大。他準備將罪犯們在get

兩座監獄內從新分配,以求產生的衝突事件影響力都較小,從而保住本身的烏紗帽。假設只

要處於同一監獄內的某兩個罪犯間有仇恨,那麼他們必定會在每一年的某個時候發生摩擦。那

麼,應如何分配罪犯,才能使Z 市長看到的那個衝突事件的影響力最小?這個最小值是少?

輸入描述  Input Description

第一行爲兩個正整數N 和M,分別表示罪犯的數目以及存在仇恨的罪犯對數。

接下來的M 行每行爲三個正整數aj,bj,cj,表示aj 號和bj 號罪犯之間存在仇恨,其怨氣值爲cj。數據保證且每對罪犯組合只出現一次。

輸出描述  Output Description

共1 行,爲Z 市長看到的那個衝突事件的影響力。若是本年內監獄

中未發生任何衝突事件,請輸出0。

樣例輸入  Sample Input

4 6

1 4 2534

2 3 3512

1 2 28351

1 3 6618

2 4 1805

3 4 12884

樣例輸出  Sample Output

3512

數據範圍及提示  Data Size & Hint

罪犯之間的怨氣值以下面左圖所示,右圖所示爲罪犯的分配方法,市長看到的衝突事件

影響力是3512(由2 號和3 號罪犯引起)。其餘任何分法都不會比這個分法更優。

【數據範圍】

對於30%的數據有N≤ 15。

對於70%的數據有N≤ 2000,M≤ 50000。

對於100%的數據有N≤ 20000,M≤ 100000。

 1 /*此題各類作法都有,但最簡單的方法仍是並查集。開一個兩倍的並查集表示犯人的集合及其補集(犯人的敵人所在的集合),排序按怨念從大到小往集合裏放,發現衝突直接輸出就能夠了。
 2 */
 3 #define N 20010
 4 #include<iostream>
 5 using namespace std;
 6 #include<cstdio>
 7 #include<algorithm>
 8 #define M 100010
 9 int n,m,father[N<<1];
10 struct Edge{
11     int a,b,c;
12     bool operator <(Edge P)
13     const{return c>P.c;}
14 }edge[M];
15 int find(int x)
16 {
17     return (father[x]==x)?x:father[x]=find(father[x]);
18 }
19 int main()
20 {
21     scanf("%d%d",&n,&m);
22     for(int i=1;i<=m;++i)
23        scanf("%d%d%d",&edge[i].a,&edge[i].b,&edge[i].c);
24     sort(edge+1,edge+m+1);
25     for(int i=1;i<=2*n;++i)
26       father[i]=i;
27     for(int i=1;i<=m;++i)
28     {
29         int x1=find(edge[i].a);
30         int y1=find(edge[i].b);
31         if(x1==y1)
32         {
33             printf("%d",edge[i].c);
34             return 0;
35         }
36         father[y1]=find(edge[i].a+n);/*a的敵人所在集合爲a+n,把y1所在的整個集合與a+n合併*/
37         father[x1]=find(edge[i].b+n);
38     }
39     printf("0");
40     return 0;
41 }
相關文章
相關標籤/搜索