首页 > 其他分享 >洛谷题单指南-集合-P1525 [NOIP2010 提高组] 关押罪犯

洛谷题单指南-集合-P1525 [NOIP2010 提高组] 关押罪犯

时间:2024-03-22 21:11:56浏览次数:24  
标签:P1525 NOIP2010 int 洛谷题 仇人 罪犯 集合 find 仇恨

原题链接:https://www.luogu.com.cn/problem/P1525

题意解读:有很多罪犯,要关到两座监狱,有一些罪犯之间有仇,并且可以量化出仇恨值,如果关在一起就会冲突,造成的影响就是仇恨值,要使得造成的影响最小,如果可以完全不起冲突,输出0。

解题思路:

首先,要让冲突影响最小化,显然应该把仇恨大的罪犯分开。

将所有罪犯关系、仇恨值按仇恨值大小降序排序

遍历每一对罪犯,判断他们是否已经在同一个集合(监狱)

如果已经属于同一个集合,则输出他们的仇恨值,即为答案。

如果不属于同一个集合,就要将两人分到两个集合(监狱),问题的关键来了,如何分配罪犯?

初始时,如果两人之前都没有仇人,则不着急合并,记录下两人为各自的仇人

接下来,如果两人能找到各自仇人,则将其与对方的仇人放在一个集合。(解释:a、b两人,a如果已经有仇人了,说明a和仇人的仇恨值更大,因为是在前面遍历到,a显然不能和其仇人分到一个集合,应该将b跟a的仇人分到一个集合,同样,a应该跟b的仇人分到一个集合)

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 20005, M = 100005;

int p[N]; //并查集,罪犯所属的集合

//查找x所在集合
int find(int x)
{
    if(p[x] == x) return p[x];
    return p[x] = find(p[x]);
}
//将x、y合并
void merge(int x, int y)
{
    p[find(x)] = find(y);
}

struct node
{
    int a, b, c; //a 和 b的怨气值c
} s[M];

bool cmp(node x, node y)
{
    return x.c >= y.c;
}

int enemy[N]; //存储已出现的每个人的敌人-存在仇恨值的人
int n, m;

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= m; i++)
    {
        cin >> s[i].a >> s[i].b >> s[i].c;
    }

    for(int i = 1; i <= n; i++) p[i] = i;
    sort(s + 1, s + m + 1, cmp); //按仇恨值降序排序
    bool nowar = true; //是否没有任何冲突
    for(int i = 1; i <= m; i++)
    {
        int u = s[i].a, v = s[i].b;
        if(find(u) == find(v)) //如果两个人已经属于同一个集合,则无法再划分,此时的仇恨值即答案
        {
            cout << s[i].c;
            nowar = false; //说明会产生冲突
            break;
        }
        else
        {
            if(!enemy[u]) enemy[u] = v; //如果u没有敌人,给u设置敌人v
            else merge(enemy[u], v); //如果u有敌人,把v和u的敌人分到一个集合
            if(!enemy[v]) enemy[v] = u; //如果v没有敌人,给v设置敌人u
            else merge(enemy[v], u); //如果v有敌人,把u和v的敌人分到一个集合
        }
    }    
    if(nowar) cout << 0; //如果没有任何冲突,输出0

    return 0;
}

 

标签:P1525,NOIP2010,int,洛谷题,仇人,罪犯,集合,find,仇恨
From: https://www.cnblogs.com/jcwy/p/18090427

相关文章

  • 洛谷题单指南-集合-P1102 A-B 数对
    原题链接:https://www.luogu.com.cn/problem/P1102题意解读:前文https://www.cnblogs.com/jcwy/p/18043197介绍了二分和双指针的做法,本文介绍hash的做法。解题思路:定义map<int,int>h,保存每个数+c出现的个数同样,先将所有数由小到大哦排序遍历每一个数x,答案累加ans+=h[x]然......
  • 洛谷题单指南-集合-P5266 【深基17.例6】学籍管理
    原题链接:https://www.luogu.com.cn/problem/P5266题意解读:本题考察map的应用。解题思路:直接使用map即可解题。100分代码:#include<bits/stdc++.h>usingnamespacestd;map<string,int>h;stringname;intn,op,score;intmain(){cin>>n;while(n--)......
  • 洛谷题单指南-集合-P5250 【深基17.例5】木材仓库
    原题链接:https://www.luogu.com.cn/problem/P5250题意解读:根据题目要求,需要一种数据结构,支持去重、排序、logN的查找,set是最合适的。解题思路:先回顾一下set的关键操作:设set<int>s;1、添加:s.insert(x)2、查询个数:s.count(x)3、查找第一个>=x的元素,返回迭代器:set<int>::iter......
  • 洛谷题单指南-集合-P3370 【模板】字符串哈希
    原题链接:https://www.luogu.com.cn/problem/P3370题意解读:本题要求理解哈希的原理,自行建立哈希表解题,如果直接使用map,就不推荐。解题思路:先介绍哈希的原理1、什么是哈希?什么是哈希表?先从一个问题出发:给定不超过105个整数(取值1~109),要统计不重复整数的数量。首先,如果取值范围......
  • 洛谷题单指南-集合-P1536 村村通
    原题链接:https://www.luogu.com.cn/problem/P1536题意解读:城镇之间现有的道路关系可以将城镇划分的若干集合,每个集合内的城镇是互通的,要计算最少增加多少条道路,使得每个集合都相通。解题思路:利用并查集,统计一共出现多少个集合,即p[i]=i的数量,最少的道路数即集合数-1,即可把所......
  • 洛谷题单指南-集合-P1551 亲戚
    原题链接:https://www.luogu.com.cn/problem/P1551题意解读:要判断两人是否是亲戚,只需要看两人是否属于一个集合,基于所有已知的亲戚关系,可以建立多个有亲戚关系的集合,这个过程可以借助并查集。解题思路:并查集:1、定义并查集是一种树形数据结构,本质上是多棵树,每棵树表示一个集合,......
  • 洛谷题单指南-二叉树-P1185 绘制二叉树
    原题链接:https://www.luogu.com.cn/problem/P1185题意解读:在表格中绘制二叉树,有几个关键点1、结点用小写字母o 表示,对于一个父亲结点,用 / 连接左子树,用 \连接右子树,表格其余地方填空格。2、第m层结点若两个属于同一个父亲,那么它们之间由 3个空格隔开;若两个结点相邻但......
  • 洛谷题单指南-二叉树-P3884 [JLOI2009] 二叉树问题
    原题链接:https://www.luogu.com.cn/problem/P3884题意解读:要计算二叉树的深度、宽度、节点间的距离,深度、宽度的概念很好理解,节点间的距离描述是:节点u,v之间的距离表示从u到v的最短有向路径上向根节点的边数的两倍加上向叶节点的边数。说人话就是:u到v的距离=uv最近公共祖先到u......
  • 洛谷题解 - B3850 [GESP202306 四级] 幸运数
    目录题目描述输入格式输出格式样例#1样例输入#1样例输出#1代码题目描述小明发明了一种“幸运数”。一个正整数,其偶数位不变(个位为第111位,十位为第......
  • 洛谷题单指南-二叉树-P1030 [NOIP2001 普及组] 求先序排列
    原题链接:https://www.luogu.com.cn/problem/P1030题意解读:已知中序、后序,求先序。解题思路:与洛谷题单指南-二叉树-P1827[USACO3.4]美国血统AmericanHeritage非常类似,不在介绍过程,直接给出代码。100分代码:#include<bits/stdc++.h>usingnamespacestd;stringin,post......