zoukankan      html  css  js  c++  java
  • Luogu P1525 [NOIp2010提高组]关押罪犯 | 并查集

    题目链接

    这一道题,我用了并查集来做。

    在此题中,并查集的作用就是:将同一个监狱里的罪犯合并到一起。
    思路:将每对罪犯之间的怨气值从大到小排序,再依次把他们分到不同的两个监狱里,当发现这一对罪犯已经在同一个监狱里时,就说明他们已经不能再分开了(分开了就不是最优了,仔细想想为什么)。此时,这一对罪犯之间的怨气值就是答案。值得注意的是,当没有冲突发生时,要记得输出0。那么,我们应该如何用并查集实现以上的思路呢?首先说几个关键词语的含义:
    1、“敌人”:如果一对罪犯被分到两个不同的监狱里,那么他们就互为“敌人”。
    2、“朋友”:如果一对罪犯被分到一个监狱里,那么他们就互为“朋友”。
    需要明确的一点是“敌人”的“敌人”,就是“朋友”。

    当分开一对罪犯时(假设他们的名字叫x和y),若x还没有“敌人”,那么就记录y为x的“敌人”(因为他们被分开了嘛);否则就把y所在的集合与x的“敌人”所在的集合合并,这是因为x是y的“敌人”,所以x的“敌人”就是y的“敌人”的“敌人”(即“朋友”),可以发现x的“敌人”和y一定是关在同一监狱里的,然后再对y的“敌人”也这样处理一遍就行了。这样我们就达到了把同一个监狱里的罪犯合并到一起的目的,处理时若发现此时处理的这一对罪犯已经在同一集合中了,则输出他们之间的怨气值作为答案。
    
    
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
        using namespace std;
    struct edge//存罪犯之间的怨气关系 
    {
        int u;
        int v;
        int w;
    }e[100005];
    bool cmp(edge x,edge y)//将怨气值从大到小排序的排序函数 
    {
        return x.w>y.w;
    }
        //f为用作实现并查集的数组,表示的是第i个罪犯的“祖先”是谁,enemy储存的是第i个罪犯的某个敌人 
        int f[20005],enemy[20005];
    int find_(int x)//并查集查找函数 
    {
        if(f[x]==x) return x;
        return f[x]=find_(f[x]);
    }
    void merge_(int x,int y)//并查集合并函数 
    {
        int t1=find_(x),t2=find_(y);
        if(t1!=t2) f[t2]=t1;
        return;
    }
    int main()
    {
        int n=0,m=0;
        scanf("%d%d",&n,&m); 
        for(int i=1;i<=n;i++) f[i]=i;//并查集初始化 
        for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        sort(e+1,e+m+1,cmp);//将怨气值从大到小排序 
        for(int i=1;i<=m;i++)
        {
            if(find_(e[i].u)==find_(e[i].v))//如果这一对罪犯已经在同一个监狱里 
            {
                printf("%d",e[i].w);//直接输出他们之间的怨气值 
                return 0;//结束程序 
            }
            //如果这一对罪犯仍能分开 
            if(!enemy[e[i].u]) enemy[e[i].u]=e[i].v;//如果u还没有敌人,那么v就是他的敌人 
                else merge_(e[i].v,enemy[e[i].u]);//否则,就将v与u的敌人合并 
            if(!enemy[e[i].v]) enemy[e[i].v]=e[i].u;//如果v还没有敌人,那么u就是他的敌人 
                else merge_(e[i].u,enemy[e[i].v]);//否则,就将u与v的敌人合并 
        }
        printf("%d",0);//记得输出0 
        return 0;
    }
  • 相关阅读:
    第一、二章读书笔记
    # 学号 20191221 《Python程序设计》实验一报告
    20191221实验四实验报告
    学号:20191221,《python实验设计》实验报告三
    20191221实验二报告
    快速浏览教材遇到
    何应霆 20191221
    2019-2020-1 20191319 《信息安全专业导论》第3周学习总结
    2019-2020-1 20191319《信息安全专业导论》第二周学习总结
    师生关系
  • 原文地址:https://www.cnblogs.com/wozaixuexi/p/8453557.html
Copyright © 2011-2022 走看看