先理解題目可以把這題目抽象為 把一些點放入兩個集合中,使每個集合中的點與點的敵對關係的最大值最小
儲存關係可以想到用並查集
然後根據貪心思想從關係最大的開始,這樣能使集合中的敵對關係的最大值最小
將有敵對關係的點放到不同的集合裡。從大到小進行決策直到發現有某一組組合已經在同乙個監獄裡,那麼輸出他們的仇恨值就是最終的答案。現在問題又來了,第一組敵對點可以輕鬆地隨意安排到兩個集合中,但是從第二組開始,兩個點到底應該各自去哪乙個集合呢?
這時要改變思路,既然維護點在哪乙個集合不方便,那麼我們乾脆維護某兩個敵對點在乙個集合了。考慮到並查集的本職工作是維護某兩點在乙個集合,不能很好地處理不在乙個集合的情況,所以我們要曲線救國,通過儲存某個點的「敵人」集合來代表和他不在乙個監獄的罪犯,間接地實現維護某兩點不在乙個集合的情況。在加入關係的時候進行判斷,如果某兩點已經在乙個集合,說明他們無論如何也安排不到不同的兩個監獄了,輸出仇恨值即可
按照敵對關係的大小從大到小進行排序
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 的罪犯被關押在同一監獄,他...