Vijos 1776 關押罪犯 【並查集+貪心】
阿新 • • 發佈:2017-07-19
第一個 ace i++ space 壓力 sin 們的 所有 cin 題目:
S城現有兩座監獄,一共關押著N名罪犯,編號分別為1~N。他們之間的關系自然也極不和諧。很多罪犯之間甚至積怨已久,如果客觀條件具備則隨時可能爆發沖突。我們用“怨氣值”(一個正整數值)來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之間的積怨越多。如果兩名怨氣值為c的罪犯被關押在同一監獄,他們倆之間會發生摩擦,並造成影響力為c的沖突事件。每年年末,警察局會將本年內監獄中的所有沖突事件按影響力從大到小排成一個列表,然後上報到S城Z市長那裏。公務繁忙的Z市長只會去看列表中的第一個事件的影響力,如果影響很壞,他就會考慮撤換警察局長。在詳細考察了N名罪犯間的矛盾關系後,警察局長覺得壓力巨大。他準備將罪犯們在兩座監獄內重新分配,以求產生的沖突事件影響力都較小,從而保住自己的烏紗帽。假設只要處於同一監獄內的某兩個罪犯間有仇恨,那麽他們一定會在每年的某個時候發生摩擦。那麽,應如何分配罪犯,才能使Z市長看到的那個沖突事件的影響力最小?這個最小值是多少?
分析:
反正只看最大的怨氣值,從貪心的方面考慮,我們的目的就是在可能的情況下,盡量把怨氣值大的分開。於是首先想到了先排序,從最大的死對頭入手。在這個題目中,我們一定要把焦點放在對立或同伴關系上,而不是關註具體誰在哪一個監獄中。於是我們把一對對死對頭從大到小分別分開,直到我們發現有一對死對頭已經在同一個監獄中,如果要分開他們,就必須放棄之前的分配造成更大的損失,這時該死對頭的怨氣值就是無論如何也不能減小的最大值了。
此題可以用並查集實現,也可以用二分圖,我這裏用並查集。
下面是參考代碼:
#include <iostream> #include <cstdio> #includeView Code<algorithm> using namespace std; struct cc{int a,b,c;} crime[500000]; int n,m; int f[500001]; bool comp(const cc &a,const cc &b){return a.c>b.c;} int find(int x) { if(f[x]!=x) f[x]=find(f[x]); else return x; return f[x]; } int main(int argc, char** argv) { cin>>n>>m; for(int i=1;i<=m;i++) cin>>crime[i].a>>crime[i].b>>crime[i].c; for(int i=1;i<=n*2;i++) f[i]=i; sort(crime+1,crime+1+m,comp); for(int i=1;i<=m;i++) { int x=find(crime[i].a); int y=find(crime[i].b); if(x==y) { cout<<crime[i].c; return 0; } f[y]=find(crime[i].a+n); f[x]=find(crime[i].b+n); } cout<<0; return 0; }
Vijos 1776 關押罪犯 【並查集+貪心】