1. 程式人生 > >Luogu1525 關押罪犯

Luogu1525 關押罪犯

原題連結:https://www.luogu.org/problemnew/show/P1525

關押罪犯

題目描述

S S 城現有兩座監獄,一共關押著 N N 名罪犯,編號分別為 1

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

每年年末,警察局會將本年內監獄中的所有衝突事件按影響力從大到小排成一個列表,然後上報到 S S Z

Z 市長那裡。公務繁忙的 Z Z 市長只會去看列表中的第一個事件的影響力,如果影響很壞,他就會考慮撤換警察局長。

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

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

輸入輸出格式
輸入格式:

每行中兩個數之間用一個空格隔開。第一行為兩個正整數 N , M N,M ,分別表示罪犯的數目以及存在仇恨的罪犯對數。接下來的 M M 行每行為三個正整數a j , b j , c j _j,b_j,c_j ,表示 a j a_j 號和 b j b_j 號罪犯之間存在仇恨,其怨氣值為 c j c_j ​ 。資料保證 1 < a j b j N , 0 < c j 1 , 000 , 000 , 000 1<a_j≤b_j≤N ,0 < c_j≤ 1,000,000,000 ,且每對罪犯組合只出現一次。

輸出格式:

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

輸入輸出樣例
輸入樣例#1:

4 6
1 4 2534
2 3 3512
1 2 28351
1 3 6618
2 4 1805
3 4 12884

輸出樣例#1:

3512

說明
【輸入輸出樣例說明】

罪犯之間的怨氣值如下面左圖所示,右圖所示為罪犯的分配方法,市長看到的衝突事件影響力是 3512 3512 (由 2 2 號和 3 3 號罪犯引發)。其他任何分法都不會比這個分法更優。

【資料範圍】

對於 30 % 30\% 的資料有 N 15 N≤ 15
對於 70 % 70\% 的資料有 N 2000 , M 50000 N≤ 2000,M≤ 50000
對於 100 % 100\% 的資料有 N 20000 , M 100000 N≤ 20000,M≤ 100000

題解

聯賽前做水題系列。

敵對的罪犯按照怨氣值從大到小排序,把怨氣值大的罪犯儘量分到兩個監獄裡,兩個監獄分別上兩個並查集即可。

程式碼
#include<bits/stdc++.h>
using namespace std;
const int M=2e4+5;
struct sd{int a,b,c;}cri[M<<3];
bool operator <(sd a,sd b){return a.c>b.c;}
int f[M],eni[M],n,m;
int root(int v){return f[v]==v?v:f[v]=root(f[v]);}
void in(){scanf("%d%d",&n,&m);for(int i=1;i<=m;++i)scanf("%d%d%d",&cri[i].a,&cri[i].b,&cri[i].c);}
void ac()
{
	for(int i=1;i<=n;++i)f[i]=i;
	sort(cri+1,cri+1+m);
	for(int i=1,a,b,c;i<=m;++i)
	{
		a=cri[i].a,b=cri[i].b;
		if(root(a)==root(b))printf("%d",cri[i].c),exit(0);
		eni[a]?f[f[b]]=root(eni[a]):eni[a]=b;
		eni[b]?f[f[a]]=root(eni[b]):eni[b]=a;
	}
	puts("0");
}
int main(){in(),ac();}