洛谷P1525 关押罪犯
P1525 關押罪犯
題目描述
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
說明
【輸入輸出樣例說明】罪犯之間的怨氣值如下面左圖所示,右圖所示為罪犯的分配方法,市長看到的沖突事件影響力是3512(由2 號和3 號罪犯引發)。其他任何分法都不會比這個分法更優。
【數據范圍】對于30%的數據有N≤ 15。對于70%的數據有N≤ 2000,M≤ 50000。對于100%的數據有N≤ 20000,M≤ 100000。
再經典不過的一道題
兩種做法:
1.并查集
對于每個點存兩個集合,一個是和他同監獄的,一個是和他不同監獄的
將怨恨值從大到小排,循環每個怨恨關系,要防止沖突的出現,就要使兩人不在同一監獄中,并且與其中一個人不在同一監獄的人一定與另一個人在同一監獄
如果查到怨恨關系對應的兩個人已經在統一監獄中了,由于怨恨關系是從大到小排列的,所以這一定是最大的一個,直接輸出
2.二分+染色
題目要求最小化最大值,不難想到要用二分答案
由于只有兩個監獄存在,染色就只需要染兩種,分別對應兩個監獄中的人
答案的最大可能值和最小可能值很顯然,然后就是判斷的問題了
判斷也不難,就是神搜與其有關系的人,只要怨恨值大于期望值,就把他倆放到不同監獄里,如果兩人已經被安排到同一個監獄,則說明這個期望值是不可行的
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define maxn 20000*3 #define maxm 100000*3 int fa[maxn],n,m; struct node{int from,to,v;}e[maxm]; int cmp(node a,node b){return a.v>b.v;} int find(int x){if(fa[x]==x)return fa[x];else return fa[x]=find(fa[x]); } int main(){scanf("%d%d",&n,&m);int x,y,z;for(int i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&z);e[i].from=x;e[i].to=y;e[i].v=z;}sort(e+1,e+m+1,cmp);for(int i=1;i<=n*2;i++)fa[i]=i;for(int i=1;i<=m;i++){int f1=find(e[i].from);int f2=find(e[i].to);if(f1==f2){printf("%d",e[i].v);return 0;}fa[f1]=find(e[i].to+n);fa[f2]=find(e[i].from+n);}printf("0");return 0; } 并查集 #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define maxm 100010 #define maxn 20010 int n,head[maxm*2],m,num,l,r,vis[maxn]; struct node{int to,pre,v; }e[maxm*2]; bool flag; void Insert(int from,int to,int v){e[++num].to=to;e[num].v=v;e[num].pre=head[from];head[from]=num; } void dfs(int fa,int now,int limit){if(flag)return;for(int i=head[now];i;i=e[i].pre){int to=e[i].to;if(e[i].v>limit&&to!=fa){if(!vis[to]){vis[to]=-vis[now];dfs(now,to,limit);}else if(vis[to]==vis[now]){flag=1;return;}}} } bool check(int x){memset(vis,0,sizeof(vis));flag=false;for(int i=1;i<=n;i++){if(!vis[i]){vis[i]=1;dfs(i,i,x);}}if(flag)return false;return true; } int main(){scanf("%d%d",&n,&m);int x,y,z;for(int i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&z);r=max(r,z);Insert(x,y,z);Insert(y,x,z);}while(l<=r){int mid=(l+r)>>1;if(check(mid))r=mid-1;else l=mid+1;}printf("%d",l); } 二分+染色轉載于:https://www.cnblogs.com/thmyl/p/7040361.html
總結
以上是生活随笔為你收集整理的洛谷P1525 关押罪犯的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 18、Java并发性和多线程-饥饿与公平
 - 下一篇: 梦到穿花鞋是什么意思