洛谷 P1525 关押罪犯 并查集变形 结构体排序 重写cmp函数

题目链接:

https://www.luogu.com.cn/problem/P1525

参考博客:

https://www.luogu.com.cn/blog/chtholly20094/solution-p1525

这个博客写的很棒,建议复习时再看

算法:

并查集

思路:

1:并查集:但因为它们带有权值,因此排序是必须的,我们要尽可能让危害大的罪犯在两个监狱里

2:那么,再结合敌人的敌人和自己在一个监狱的规律合并

3:当查找时发现其中两个罪犯不可避免地碰撞到一起时,只能将其输出并结束;没有冲突时输出0

#include <bits/stdc++.h>

using namespace std;
struct date//结构体便于排序的变换
{
    int x,y,z;
}f[100002];
int n,m,a[20002],b[20002],i;

inline void init()
{
    for(int i=1;i<=n;i++)
        a[i]=i;
}

inline bool cmp(date a,date b)//重写cmp函数
{
    return a.z>b.z;
}

inline int find(int x)
{
    if(a[x]!=x)a[x]=find(a[x]);
    return a[x];
}

//并查集合并
inline void ad(int x,int y)
{
    x=find(a[x]);
    y=find(a[y]);
    if(x!=y)a[x]=y;
}

//判断是否在同一棵树中,即是否在同一个监狱中
inline bool check(int x,int y)
{
    x=find(x);
    y=find(y);
    if(x==y)return true;
    else return false;
}

int main()
{
    ios::sync_with_stdio(0);
    scanf("%d%d",&n,&m);
    init();
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&f[i].x,&f[i].y,&f[i].z);
    sort(f+1,f+m+1,cmp);
    //写的很巧妙,到m+1恰好说明没有发生冲突 ,check()函数将会返回true,cout<<f[m+1].z=0
    for(int i=1;i<=m+1;i++)
    {
        if(check(f[i].x,f[i].y))//如果两个罪犯已经在同一监狱就输出 ,并退出
        {
            printf("%d",f[i].z);
            break;
        }
        else//a数组代表他下标的朋友,在同一棵树中,同一个强连通分量中;b数组代表他下标的敌人
        {//如果f[i].x没有敌人就把f[i].y标记为敌人,如果有敌人了,就把敌人f[i].y和敌人b[f[i].x]合并
            if(!b[f[i].x])b[f[i].x]=f[i].y;
            else ad(b[f[i].x],f[i].y);
            if(!b[f[i].y])b[f[i].y]=f[i].x;
            else ad(b[f[i].y],f[i].x);
        }
    }
    return 0;
}
发布了117 篇原创文章 · 获赞 37 · 访问量 6571

猜你喜欢

转载自blog.csdn.net/aiwo1376301646/article/details/104203928