洛谷P1525 [noip2010]关押罪犯 贪心+并查集

题目链接:https://www.luogu.com.cn/problem/P1525

题意是给定n个罪犯,有m个罪犯之前有怨气值,若有怨气值为c的一对罪犯放在同一个监狱会产生影响力为c的冲突。将罪犯分成两部分使得影响力最大的冲突事件最小。

一个并查集+贪心的好方法:把怨气值按照降序排序,尽量让c大的罪犯不放在同一个监狱,直到两个罪犯必须在同一个监狱时,就输出他们的c。具体使用简单的带权并查集实现:若v[x]=0表示x和par[x]在同一个监狱,v[x]=1则不在,然后按照带权并查集的方法处理即可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxm=1000+10;
 5 const int maxn=200+10;
 6 
 7 struct st{    int x,y,num;}a[maxm];
 8 int par[maxn],v[maxn];
 9 int n,m,i,j,k;
10 
11 bool cmp(st p,st q){
12     return p.num>q.num;
13 }
14 
15 int find(int x){ //带权并查集,v[x]=0表示x与par[x]在相同监狱 
16     if (par[x]==x) return x;
17     else{
18         int p=par[x];
19         par[x]=find(par[x]);
20         v[x]=(v[x]+v[p])%2;
21     }
22     return par[x];
23 }
24 
25 int main(){
26     //freopen("luogu1525.txt","r",stdin);
27     scanf("%d%d",&n,&m);
28     memset(v,0,sizeof(v));
29     for (i=1;i<=n;i++) par[i]=i;
30     for (i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].num);
31     sort(a+1,a+m+1,cmp);
32     for (i=1;i<=m;i++){
33         int xx=find(a[i].x);int yy=find(a[i].y);
34         if (xx==yy){
35             int t=(v[a[i].x]-v[a[i].y])%2; //*
36             if (t==0){ //a[i].x和a[i].y在同一个监狱 
37                 printf("%d\n",a[i].num);
38                 return 0;
39             }
40         }
41         else {
42             par[xx]=yy;
43             v[xx]=(v[a[i].y]-v[a[i].x]+1)%2; //*
44         }
45     }
46     printf("%d\n",0);
47     //fclose(stdin);
48     return 0;
49 }
洛谷1525

 

posted @ 2020-05-18 09:35  coastal_taipan  阅读(121)  评论(0编辑  收藏  举报