luogu1525 關押罪犯

2021-08-03 23:53:56 字數 3025 閱讀 2970

題目描述

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

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

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

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

輸入輸出格式

輸入格式:

輸入檔案的每行中兩個數之間用乙個空格隔開。第一行為兩個正整數n 和m,分別表示罪犯的數目以及存在仇恨的罪犯對數。接下來的m 行每行為三個正整數aj,bj,cj,表示aj 號和bj 號罪犯之間存在仇恨,其怨氣值為cj。資料保證1 < aj= < =bj < =n ,0 < cj≤ 1,000,000,000,且每對罪犯組合只出現一次。

輸出格式:

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

輸入輸出樣例

輸入樣例#1:

4 6

1 4 2534

2 3 3512

1 2 28351

1 3 6618

2 4 1805

3 4 12884

輸出樣例#1:

3512

分析:

解法一:

二分題——好想不好寫

(這就給我們乙個啟示,一旦遇到使最小值最大或最大值最小,就考慮二分)

我們二分一下編號(哪條邊會作為最大邊)

那麼困難就在於如何判定,

若mid合法,則同乙個監獄裡的所有衝突值都要小於等於mid

這就等價於:所有衝突值大於k的兩個犯人必須被關押在不同的監獄

我們把衝突值從大到下排序並進行新增,

若當前衝突值 >v[mid],那麼這兩個犯人一定會分到不同監獄,

如果不可避免會發生衝突,則該方案不合法,將範圍擴大,

判定的時候dfs即可

一直re,注意陣列大小

這裡寫**片

#include

#include

#include

#include

using

namespace

std;

const

int n=20010;

int n,m;

struct node;

node way[200010]; //雙向加邊,注意陣列大小

int st[n],tot=0;

int p[n],flag,a[100010]; //a的範圍和m一樣

void add(int u,int w,int z)

void dfs(int now,int jh,int mid) //now,集合

else

if (p[way[i].y]==p[now])}}

}int pd(int mid)

void doit()

printf("%d",a[l]); //a[l]

}int main()

sort(a+1,a+1+m);

doit();

return

0;}

解法二:

並查集——不好想好寫

把點分成兩部:1~n 是友部,n+1~2*n是敵部,

友部和敵部之間互不相容,每個部中是可以相容的(衝突值不大)

把邊從大到小排序並新增,

利用並查集判定每條邊的兩個端點分別在哪個部裡,

只要能夠分到不同部裡,就這樣貪心的分下去

注意,如果兩個端點確定要分在不同的地方,那在union的時候

該點的祖先就union到對方的敵人那裡

for (int i=1;i<=m;i++)

f[r1]=find(w+n); //預設每乙個點和ta+n的點為敵人(不能在乙個集合中)

f[r2]=find(u+n); //敵人的敵人就是朋友

//注意這裡修改的是r1,r2,畢竟只有修改並查集的標誌節點才能把集合合併

}

我這個zz一直wa,後來才發現是並查集中的find寫掛了

我這個zz在 return f[a]; 前加了乙個else

就這樣wa挺了

這裡寫**片

#include

#include

#include

#include

using

namespace

std;

const

int n=20010;

int n,m;

struct node;

node way[100010];

int f[n<<1];

int cmp(const node &a,const node &b)

int find(int a)

void doit()

f[r1]=find(w+n); //預設每乙個點和ta+n的點為敵人(不能在乙個集合中)

f[r2]=find(u+n); //敵人的敵人就是朋友

//注意這裡修改的是r1,r2,畢竟只有修改並查集的標誌節點才能把集合合併

}printf("0");

}int main()

Luogu1525 關押罪犯

題目描述 s ss城現有兩座監獄,一共關押著n nn名罪犯,編號分別為1 n 1 n1 n。他們之間的關係自然也極不和諧。很多罪犯之間甚至積怨已久,如果客觀條件具備則隨時可能爆發衝突。我們用 怨氣值 乙個正整數值 來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之間的積怨越多。如果兩名怨氣值...

luogu1525 關押罪犯

題目描述 s 城現有兩座監獄,一共關押著n 名罪犯,編號分別為1 n。他們之間的關係自然也極不和諧。很多罪犯之間甚至積怨已久,如果客觀條件具備則隨時可能爆發衝突。我們用 怨氣值 乙個正整數值 來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之間的積怨越多。如果兩名怨氣值為c 的罪犯被關押在同...

P1525 關押罪犯

s 城現有兩座監獄,一共關押著n 名罪犯,編號分別為1 n。他們之間的關係自然也極不和諧。很多罪犯之間甚至積怨已久,如果客觀條件具備則隨時可能爆發衝突。我們用 怨氣值 乙個正整數值 來表示某兩名罪犯之間的仇恨程度,怨氣值越大,則這兩名罪犯之間的積怨越多。如果兩名怨氣值為c 的罪犯被關押在同一監獄,他...