zcmu-1960
1960: 關押罪犯
Time Limit:?1 Sec??Memory Limit:?128 MBSubmit:?22??Solved:?7
[Submit][Status][Web Board]
Description
S 城現有兩座監獄,一共關押著 N 名罪犯,編號分別為 1~N。他們之間的關系自然也極 不和諧。很多罪犯之間甚至積怨已久,如果客觀條件具備則隨時可能爆發沖突。我們用“怨 氣值”(一個正整數值)來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之 間的積怨越多。如果兩名怨氣值為 c 的罪犯被關押在同一監獄,他們倆之間會發生摩擦,并 造成影響力為 c 的沖突事件。 每年年末,警察局會將本年內監獄中的所有沖突事件按影響力從大到小排成一個列表, 然后上報到 S 城 Z 市長那里。公務繁忙的 Z 市長只會去看列表中的第一個事件的影響力, 如果影響很壞,他就會考慮撤換警察局長。 在詳細考察了 N 名罪犯間的矛盾關系后,警察局長覺得壓力巨大。他準備將罪犯們在 兩座監獄內重新分配,以求產生的沖突事件影響力都較小,從而保住自己的烏紗帽。假設只 要處于同一監獄內的某兩個罪犯間有仇恨,那么他們一定會在每年的某個時候發生摩擦。那 么,應如何分配罪犯,才能使 Z 市長看到的那個沖突事件的影響力小?這個小值是多少?
Input
對于 30%的數據有 N≤15。
對于 70%的數據有 N≤2000,M≤50000。
對于 100%的數據有 N≤20000,M≤100000。
Output
輸出文件 prison.out 共 1 行,為 Z 市長看到的那個沖突事件的影響力。如果本年內監獄 中未發生任何沖突事件,請輸出 0。
Sample Input
4 61 4 25342 3 35121 2 283511 3 66182 4 18053 4 12884Sample Output
3512HINT
思路:用并查集表示每個犯人之間的關系,在同一個集合中則說明兩人在同一個監獄,反之則不在同一個監獄。?
用類似于克魯斯卡爾的方法,先將邊排序,然后按照仇恨值的大小從大到小處理。對于每一組,先看兩個人能不能加入不同的集合,?
如果可以,將兩人加入不同的集合,如果不可以,則輸出該組仇恨值。?
用補集來表示兩個點不在一個集合中。如a和b’在同一個集合中,則a和b不在同一個集合中,不能把b直接加入另一個集合,因為會對后面的結果產生影響。?
如,3和4不在同一個集合中,但是我們現在不知道究竟是3在第一個監獄還是4在第一個監獄,所以此時用3和4‘在同一個集合中來表示3和4不在同一個集合中。
代碼:
#include<algorithm> #include<iostream> #include<cstdio> #include<cstring> using namespace std; struct node {int a , b , c; }; const int N = 100000 + 50; node man[N]; int p[N]; bool cmp(node a , node b) {return a.c > b.c; } int find(int x) {return x == p[x]?x:x=find(p[x]); } int main(int argc, char const *argv[]) {int n , m;cin >> n >> m;for (int i = 0; i < m; ++i)scanf("%d%d%d", &man[i].a, &man[i].b, &man[i].c);for (int i = 1; i <= 2*n; ++i){p[i] = i;}sort(man , man + m , cmp);for (int i = 0; i < m; ++i){int x = find(man[i].a); int y = find(man[i].b);if(x == y){cout << man[i].c << endl;return 0;}p[x] = find(man[i].b + n);p[y] = find(man[i].a + n);}printf("0\n");return 0; }
總結
- 上一篇: 数据结构之malloc()函数动态内存分
- 下一篇: java service层 事务_Jav