题目链接: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 ",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 ",0); 47 //fclose(stdin); 48 return 0; 49 }