2023年noipc 提高組複賽 第三題

2021-08-25 11:01:23 字數 1753 閱讀 1451

先理解題目可以把這題目抽象為 把一些點放入兩個集合中,使每個集合中的點與點的敵對關係的最大值最小

儲存關係可以想到用並查集

然後根據貪心思想從關係最大的開始,這樣能使集合中的敵對關係的最大值最小

將有敵對關係的點放到不同的集合裡。從大到小進行決策直到發現有某一組組合已經在同乙個監獄裡,那麼輸出他們的仇恨值就是最終的答案。現在問題又來了,第一組敵對點可以輕鬆地隨意安排到兩個集合中,但是從第二組開始,兩個點到底應該各自去哪乙個集合呢?

這時要改變思路,既然維護點在哪乙個集合不方便,那麼我們乾脆維護某兩個敵對點在乙個集合了。考慮到並查集的本職工作是維護某兩點在乙個集合,不能很好地處理不在乙個集合的情況,所以我們要曲線救國,通過儲存某個點的「敵人」集合來代表和他不在乙個監獄的罪犯,間接地實現維護某兩點不在乙個集合的情況。在加入關係的時候進行判斷,如果某兩點已經在乙個集合,說明他們無論如何也安排不到不同的兩個監獄了,輸出仇恨值即可

按照敵對關係的大小從大到小進行排序

bool cmp(node a,node b)

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

sort(b+1,b+1+m,cmp);

me

memset(di,0,sizeof(di));

memset(fu,0,sizeof(fu));

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

維護集合

在加入關係的時候進行判斷,如果某兩點已經在乙個集合,說明他們無論如何也安排不到不同的兩個監獄了,輸出仇恨值即可

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

if(di[s]==0) di[s]=d;

else hebing(d,di[s]);

if(di[d]==0) di[d]=s;

else hebing(s,di[d]);

}

完整**:

#include 

#include

#include

#include

using

namespace

std;

int n,m;

int an[20006],fu[20005],di[20005];

struct nodeb[100005];

bool cmp(node a,node b)

int cha(int x)

void hebing(int x,int y)

int main()

sort(b+1,b+1+m,cmp);

memset(di,0,sizeof(di));

memset(fu,0,sizeof(fu));

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

int s,d;

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

if(di[s]==0) di[s]=d;

else hebing(d,di[s]);

if(di[d]==0) di[d]=s;

else hebing(s,di[d]);

}cout

<

0;}

2023年 noipc 提高組複賽 第一題

題目描述 為了準備乙個獨特的頒獎典禮,組織者在會場的一片矩形區域 可看做是平面直角座標系的第一象限 鋪上一些矩形地毯。一共有 nn n 張地毯,編號從 1 到 n。現在將這些地毯按照編號從小到大的順序平行於座標軸先後鋪設,後鋪的地毯覆蓋在前面已經鋪好的地毯之上。地毯鋪設完成後,組織者想知道覆蓋地面某...

NOIP2010提高組複賽C 關押罪犯

略這題是並查集的乙個變題,先按積怨值從大到小排序,然後乙個乙個看能否完全分開,遇到的第乙個不能分開的囚犯對 如果強行分開就必然有更高的積怨值出現 就是答案。一開始想到的是按監獄數量弄個並查集,後來發現並不行,因為如果要分開一對囚犯,沒辦法決定誰一定住1號監獄,誰一定住2號監獄。後來試了下用囚犯數量弄...

洛谷 關押罪犯 NOIP2010提高組複賽

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