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;
}
Luogu P1525 [NOIp2010提高组]关押罪犯 | 并查集的更多相关文章
- NOIP2010提高组 关押罪犯 -SilverN
(洛谷P1525) 题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”( ...
- 洛谷 P1525 关押罪犯 NOIp2010提高组 (贪心+并查集)
题目链接:https://www.luogu.org/problemnew/show/P1525 题目分析 通过分析,我们可以知道,这道题的抽象意义就是把一个带边权的无向图,分成两个点集,使得两个集合 ...
- [NOIp2010提高组]关押罪犯
OJ题号:洛谷1525 思路:贪心. 先将所有的人按怨气值从大到小排一下,然后依次尝试将双方分入两个不同的监狱,如果失败(即已分入相同的监狱),则输出这个怨气值. #include<cstdio ...
- NOIP2010提高组] CODEVS 1069 关押罪犯(并查集)
这道这么简单的题目还写了这么久.. 将每个会发生冲突的两人的怒气进行排序,然后从怒气大到小,将两个人放到不同监狱中.假如两人都已经被放置且在同一监狱,这就是答案. ------------------ ...
- NOIP2010关押罪犯[并查集|二分答案+二分图染色 | 种类并查集]
题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示 ...
- 洛谷P1525关押罪犯——并查集
题目:https://www.luogu.org/problemnew/show/P1525 并查集+贪心,从大到小排序,将二人分在不同房间,找到第一个不满足的即为答案. 代码如下: #include ...
- NOIP 2010 关押罪犯 并查集 二分+二分图染色
题目描述: S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值" ...
- P1525 关押罪犯 并查集
题目描述 SS城现有两座监狱,一共关押着NN名罪犯,编号分别为1-N1−N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值) ...
- [noip2010]关押罪犯 并查集
第一次看的时候想到了并查集,但是不知道怎么实现: 标解,f[i]表示i所属的集合,用f[i+n]表示i所属集合的补集,实现的很巧妙,可以当成一个使用并查集的巧妙应用: #include<iost ...
随机推荐
- redis的集群安装
1.创建安装目录 在master ,node1 ,node2中分别创建 mkdir /usr/local/soft/redis-cluster 2.将redis 复制到redis-cluster 目录 ...
- C++快速读入
使用C++的标准cin进行读入速度比较慢,尤其是在大数据的情况下,所以我们需要使用一种方法,按照字符读入,最后再"组装"成整数.由于字符读入比数字要快,所以这样做可以提高读入速度. ...
- mysql将数据导入到另外一张操作
insert into ydcq_member_class (ClassId,signcount,UserId) select 64,2,`员工编号` from `学员名单`
- python对象引用和垃圾回收
变量="标签" 变量a和变量b引用同一个列表: >>> a = [1, 2, 3] >>> b = a >>> a.appen ...
- 浅聊Linux的五种IO模型
在日常 Coding 中,多多少少都会接触到网络 IO,就会想要深入了解一下.看了很多文章,总是云里雾里的感觉,直到读了<UNIX网络编程 卷1:套接字联网API>中的介绍后,才豁然开朗. ...
- 吴恩达--神经网络-week1-hw4
# Ref: https://blog.csdn.net/u013733326/article/details/79767169 import numpy as np import testCases ...
- 【LeetCode】300.最长递增子序列——暴力递归(O(n^3)),动态规划(O(n^2)),动态规划+二分法(O(nlogn))
算法新手,刷力扣遇到这题,搞了半天终于搞懂了,来这记录一下,欢迎大家交流指点. 题目描述: 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度. 子序列是由数组派生而来的序列,删除(或不删 ...
- java统一返回标准类型
一.前言.背景 在如今前后端分离的时代,后端已经由传统的返回view视图转变为返回json数据,此json数据可能包括返回状态.数据.信息等......因为程序猿的习惯不同所以返回json数据的格式也 ...
- 微信小程序Canvas添加水印字体,通过setGlobalAlpha设置字体透明度。
微信小程序自带的设置透明度只有setGlobalAlpha,但是CanvasContext.setGlobalAlpha设置透明度,是全局透明,整张图片都透明了.所以直接使用是不行的. 换种思路实现: ...
- scheduler源码分析——preempt抢占
前言 之前探讨scheduler的调度流程时,提及过preempt抢占机制,它发生在预选调度失败的时候,当时由于篇幅限制就没有展开细说. 回顾一下抢占流程的主要逻辑在DefaultPreemption ...