1. 程式人生 > >NOIP 2010 關押罪犯

NOIP 2010 關押罪犯

copy 排序 std hold pre 每年 -a ack 輸入格式

P1525 關押罪犯

題目描述

SS 城現有兩座監獄,一共關押著 NN 名罪犯,編號分別為 1-N1N 。他們之間的關系自然也極不和諧。很多罪犯之間甚至積怨已久,如果客觀條件具備則隨時可能爆發沖突。我們用“怨氣值”(一個正整數值)來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之間的積怨越多。如果兩名怨氣值為 cc 的罪犯被關押在同一監獄,他們倆之間會發生摩擦,並造成影響力為 cc 的沖突事件。

每年年末,警察局會將本年內監獄中的所有沖突事件按影響力從大到小排成一個列表,然後上報到S 城Z 市長那裏。公務繁忙的Z 市長只會去看列表中的第一個事件的影響力,如果影響很壞,他就會考慮撤換警察局長。

在詳細考察了 NN 名罪犯間的矛盾關系後,警察局長覺得壓力巨大。他準備將罪犯們在兩座監獄內重新分配,以求產生的沖突事件影響力都較小,從而保住自己的烏紗帽。假設只要處於同一監獄內的某兩個罪犯間有仇恨,那麽他們一定會在每年的某個時候發生摩擦。

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

輸入輸出格式

輸入格式:

每行中兩個數之間用一個空格隔開。第一行為兩個正整數 N,MN,M ,分別表示罪犯的數目以及存在仇恨的罪犯對數。接下來的 MM 行每行為三個正整數 a_j,b_j,c_jaj?,bj?,cj? ,表示 a_jaj? 號和 b_jbj? 號罪犯之間存在仇恨,其怨氣值為 c_jcj? 。數據保證 1<aj≤bj≤N ,0 < cj≤ 1,000,000,0001<ajbjN,0<cj1,000,000,000 ,且每對罪犯組合只出現一次。

輸出格式:

11 行,為 ZZ 市長看到的那個沖突事件的影響力。如果本年內監獄中未發生任何沖突事件,請輸出 00 。

輸入輸出樣例

輸入樣例#1: 復制
4 6
1 4 2534
2 3 3512
1 2 28351
1 3 6618
2 4 1805
3 4 12884
輸出樣例#1: 復制
3512

說明

【輸入輸出樣例說明】罪犯之間的怨氣值如下面左圖所示,右圖所示為罪犯的分配方法,市長看到的沖突事件影響力是 35123512 (由 22 號和 33 號罪犯引發)。其他任何分法都不會比這個分法更優。

技術分享圖片

【數據範圍】

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

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

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

思路:並查集+貪心。

先按照c從大到小排序。用並查集判斷兩個罪犯是否在同一個監獄裏。

關鍵問題在於把某個罪犯放到哪個監獄。

很容易想到,如果已經在監獄裏的罪犯和他們沒有矛盾,就隨便放。

若存在矛盾,就把他放到對立的監獄裏。

比如樣例中的1和3.就可以把3放到1對立的罪犯2所在的監獄裏。

因為是從大到小找的,所以這樣一定能滿足最優解。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 200010
#define MAXM 100010
using namespace std;
int n,m;
int fa[MAXN],col[MAXN];
struct nond{
    int a,b,c;
}v[MAXM];
int find(int x){
    if(fa[x]==x)    return x;
    else return fa[x]=find(fa[x]);
}
int cmp(nond x,nond y){
    return x.c>y.c;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&v[i].a,&v[i].b,&v[i].c);
    for(int i=1;i<=n;i++)    fa[i]=i;
    sort(v+1,v+1+m,cmp);
    for(int i=1;i<=m;i++){
        int dx=find(v[i].a);
        int dy=find(v[i].b);
        if(dx==dy){
            printf("%d",v[i].c);
            return 0;
        }
        else{
            if(col[v[i].a]==0)    col[v[i].a]=v[i].b;    
            if(col[v[i].b]==0)    col[v[i].b]=v[i].a;
            if(col[v[i].a]!=0)    fa[find(col[v[i].a])]=find(v[i].b);
            if(col[v[i].b]!=0)    fa[find(col[v[i].b])]=find(v[i].a);
        }
    }
    printf("0");
}

NOIP 2010 關押罪犯