题意:

有N个罪犯,将关至2个监狱中。其中,罪犯如果关在同一个监狱,则两两之间存在怨气值c[i]。求第一个怨气值,要求此怨气值最小。

解法:

贪心,先对怨气值从大到小排序,然后将两名罪犯关至不同的监狱。直至存在一对罪犯无法关至不同的监狱(若关至同一监狱,则会和已经关押的罪犯产生怨气,这个值\(>\)当前值,则不是最优),那么此时的怨气值就是答案。

对于并查集的维护

可以开2倍的数组。如x y是有怨气,则Union(x+n,y); Union(x,y+n);

#include<iostream>
#include<algorithm>
using namespace std;;
struct p{int x,y,h;}a[200005];
bool cmp(p x,p y){return x.h>y.h;}
int f[40050];

int fnd(int i);
void uni(int i,int k);
int main()
{
    int i;
    int n,m;
    cin>>n>>m;
    for(i=1;i<=n*2;i++)
        f[i]=i;
    for(i=1;i<=m;i++)
        cin>>a[i].x>>a[i].y>>a[i].h;
    sort(a+1,a+m+1,cmp);
    for(i=1;i<=m;i++)
    {
        if(fnd(a[i].x)==fnd(a[i].y)||fnd(a[i].x+n)==fnd(a[i].y+n))
        {
            cout<<a[i].h;
            return 0;
        }
        uni(a[i].x,a[i].y+n);
        uni(a[i].x+n,a[i].y);
    }
    cout<<"0";
    return 0;
}
int fnd(int i)
{
    if(f[i]==i)
        return i;
    return f[i]=fnd(f[i]);
}
void uni(int i,int k)
{
    if(fnd(i)!=fnd(k))
        f[fnd(i)]=fnd(k);
    return ;
}
01-18 04:03