码迷,mamicode.com
首页 > 其他好文 > 详细

【题解】P1525 关押罪犯

时间:2019-08-13 20:17:49      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:题目   struct   turn   就是   sort   class   意思   def   for   

这道题是一道比较好的并查集的题目,蒟蒻顿时感觉我学了一个假的并查集。

思路

首先,这道题的意思是:
给你 \(n\) 个点,将他们任意分成两边,求这些点之前权值最大的边尽量的小,求这个值。

我们如何用并查集来做呢?
首先,我们将所有边从大到小排序,对于每两个点 \(x\)\(y\) ,我们将 \(x\)\(y\) 的敌人放一起, \(x\)的敌人和 \(y\) 放一起,敌人的敌人就是我的朋友。
当两个点不得不连接在一起时,那么我们就输出这条边的边权,特别的,如果没有两个点被迫连在一起,那么就需要输出 \(0\)
为什么这样做是对的呢?
首先,我们的边权是从大到小排的,当第一次出现两个不得不连接在一起的点时,当前这条边的边权肯定是最大的。
那么,对于第 \(i\) 个点的敌人 \(b[i]\) ,它与 \(i\) 的连边肯定是最大的,那么对于 \(x\)\(y\)\(x\) 连上 \(y\) 的敌人肯定要比 \(x\)\(y\) 连边的权值要小,不然的话,我们就会先遍历到这条边,再遍历 \(x\)\(y\) 的这条边。
\(Code:\)

#include <iostream>
#include <cstdio>
#include <algorithm> 
#define N 100011
using namespace std;
struct Node
{
    int u,v,w;
}a[N];
int f[N],b[N];
bool cmp(Node x,Node y)
{
    return x.w>y.w;
}
int getf(int v)
{
    return f[v]==v?v:f[v]=getf(f[v]);
}
void merge(int x,int y)
{
    int t1=getf(x),t2=getf(y);
    if(t1!=t2) f[t2]=t1;
    return;
}
bool check(int x,int y)
{
    int t1=getf(x),t2=getf(y);
    if(t1==t2) return true;
    else return false;
}
int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;++i)
        scanf("%d %d %d",&a[i].u,&a[i].v,&a[i].w); 
    sort(a+1,a+m+1,cmp);
    for(int i=1;i<=n;++i) f[i]=i;
    for(int i=1;i<=m+1;++i)
    {
        int x,y;
        x=a[i].u; y=a[i].v;
        int t1=getf(x),t2=getf(y);
        if(check(x,y)) 
        {
            printf("%d",a[i].w);
            return 0;
        } 
        if(!b[x]) 
            b[x]=y;
        else 
            merge(b[x],y);
        if(!b[y]) 
            b[y]=x;
        else 
            merge(b[y],x);
    }
    return 0;
}

【题解】P1525 关押罪犯

标签:题目   struct   turn   就是   sort   class   意思   def   for   

原文地址:https://www.cnblogs.com/Call-me-zhz/p/11347995.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!