信息学奥赛一本通 1861:【10NOIP提高组】关押罪犯 | 洛谷 P1525 [NOIP 2010 提高组] 关押罪犯

【题目链接】

ybt 1861:【10NOIP提高组】关押罪犯
洛谷 P1525 [NOIP 2010 提高组] 关押罪犯

【题目考点】

1. 图论:二分图
2. 二分答案
3. 种类并查集

【解题思路】

解法1:种类并查集

一个囚犯是一个顶点,一个囚犯对可以看做一条边,每个囚犯对的怨气值是边的权值。
一个监狱的囚犯属于一个集合,也就是一个连通分量。
现在给定很多顶点和预设的边,将所有的顶点分为两个集合,每个集合中顶点之间的边都生效。求所有的集合划分方案中集合中最大边权的最小值。

为了使集合中边权最大的边最小,可以将所有边按权值从大到小排序。按权值从大到小遍历所有的边,尽量让权值大的边所连接的两个顶点不在同一个集合。如果发现某条边连接的两个顶点无法放在不同的集合,那么该边的两个顶点就必须放在相同的集合中,该边就是集合中边权最大的边。该边的边权就是所有的集合划分方案中集合中最大边权的最小值。

对于第 i i i个顶点,我们可以假想存在顶点 i + n i+n i+n,顶点 i + n i+n i+n与顶点 i i i不在同一个集合。
对于权值为 w w w的边 ( u , v ) (u, v) (u,v)

  • 如果顶点 u u u和顶点 v v v已经在同一集合,那么已经无法将 u u u v v v放到两个不同的集合,集合中存在的最大边权就是 w w w w w w就是该问题的结果。

  • 否则,让顶点 u u u和顶点 v v v不在同一个集合。由于顶点 v + n v+n v+n和顶点 v v v不在同一集合,那么顶点 u u u和顶点 v + n v+n v+n一定在同一集合,将二者所在的集合合并。
    同理,顶点 v v v和顶点 u + n u+n u+n在同一集合,将二者所在的集合合并。

设排序后,有顶点1到顶点2的边,权值为3。有顶点1到顶点3的边,权值为3,有顶点2到顶点3的边,权值为2,设总顶点数n为10。
运行上述算法

  1. 访问顶点1到顶点2的边,将顶点1和假想的与顶点2不在同一集合的顶点12合并,顶点2和假想的与顶点1不在同一集合的顶点11合并。
  2. 访问顶点1到顶点3的边,将顶点1和顶点13合并,此时1, 12, 13处于同一集合。将订单3和顶点11合并,此时2, 3, 11处于同一集合。
  3. 访问顶点2到顶点3的边,发现顶点2、3在同一集合,那么集合中最大边权为顶点2到顶点3的边的权值,为2。

解法2:二分答案+二分图判定

市长看到的冲突事件是影响力最大的冲突事件。要使影响力最大的冲突事件的影响力最小,是最大值最小问题,可以使用二分答案解决。

  • 答案变量:集合中的最大边权c
  • 最值:求最小值
  • 满足条件:将所有顶点分为两个集合,集合内顶点间的边权都小于等于c
    该条件仍然难以判断。可以反向思考,如果集合内顶点间的边权都小于等于c,那么边权大于c的边一定只能是分别连接两集合中的两个顶点。
    如果只考虑边权大于c的边,所有的边的一端是一个集合中的顶点,另一端是另一个集合中的顶点,该图就是一个二分图。
    因此二分答案满足条件为:只考虑边权大于c的边时,该图是二分图。
    可以使用染色法进行二分图判定,只有边权大于c时才通过该边访问邻接点。

可以直接二分答案边权数值。也可以先对保存边权的序列进行排序,而后在边权序列上进行二分查找目标边权的下标。

【题解代码】

解法1:种类并查集
#include<bits/stdc++.h>
using namespace std;
#define N 20005
#define M 100005
struct Edge
{int u, v, w;bool operator < (const Edge &b) const{return w > b.w;}
} e[M];
int n, m, fa[2*N], ans;
void initFa(int n)
{for(int i = 1; i <= 2*n; ++i)fa[i] = i;
}
int find(int x)
{return fa[x] = x == fa[x] ? x : find(fa[x]);
}
void merge(int x, int y)
{fa[find(x)] = find(y);
}
int main()
{cin >> n >> m;initFa(n);for(int i = 1; i <= m; ++i)cin >> e[i].u >> e[i].v >> e[i].w;sort(e+1, e+1+m);for(int i = 1; i <= m; ++i){int u = e[i].u, v = e[i].v, w = e[i].w;if(find(u) == find(v)){ans = w;break;}merge(u, v+n);merge(v, u+n);}cout << ans;return 0;
}
解法2:二分答案+二分图判定
  • 写法1:广搜二分图判定,二分答案边权数值
#include<bits/stdc++.h>
using namespace std;
#define N 20005
struct Edge
{int v, w;
};
int n, m, color[N];
vector<Edge> edge[N];
bool bfs(int sv, int c)//二分图判定,只关注大于c的边
{queue<int> que;color[sv] = 1;que.push(sv);while(!que.empty()){int u = que.front();que.pop();for(Edge e : edge[u]) if(e.w > c)//只访问权值大于c的边 {int v = e.v;if(color[v] == 0){color[v] = 3-color[u];que.push(v);}else if(color[v] == color[u])return false;}}return true;
}
bool check(int c)//只关注大于c的边时,该图是否为二分图
{memset(color, 0, sizeof(color));for(int i = 1; i <= n; ++i) if(color[i] == 0 && !bfs(i, c))return false;return true;
} 
int main()
{int a, b, c;cin >> n >> m;for(int i = 1; i <= m; ++i){cin >> a >> b >> c;edge[a].push_back(Edge{b, c});edge[b].push_back(Edge{a, c});}int l = 0, r = 1e9;while(l < r){int mid = (l+r)/2;if(check(mid))r = mid;elsel = mid+1;}cout << l;return 0;
}
  • 写法2:深搜二分图判定,二分查找下标
#include<bits/stdc++.h>
using namespace std;
#define N 20005
#define M 100005
struct Edge
{int v, w;
};
int n, m, color[N], w[M];
vector<Edge> edge[N];
bool dfs(int u, int c)
{for(Edge e : edge[u]) if(e.w > c){int v = e.v;if(color[v] == 0){color[v] = 3-color[u];if(!dfs(v, c))return false;}else if(color[v] == color[u])return false;}return true;
}
bool check(int c)//只关注大于c的边时,该图是否为二分图
{memset(color, 0, sizeof(color));for(int i = 1; i <= n; ++i) if(color[i] == 0){color[i] = 1;if(!dfs(i, c))return false;}return true;
} 
int main()
{int a, b, c;cin >> n >> m;for(int i = 1; i <= m; ++i){cin >> a >> b >> c;edge[a].push_back(Edge{b, c});edge[b].push_back(Edge{a, c});w[i] = c;}sort(w+1, w+1+m);int l = 0, r = m;//l最小应该为0,w[0]为0,当下标取到0时,结果为0,此时取所有的边,仍然是二分图。 while(l <= r){int mid = (l+r)/2;if(check(w[mid]))r = mid-1;elsel = mid+1;}cout << w[l];return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/75877.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我的NISP二级之路-01

目录 一.SSE-CMM系统安全工程-能力成熟度模型(Systems Security Engineering - Capability Maturity Model) 二.ISMS 即信息安全管理体系(Information Security Management System),是一种基于风险管理的、系统化的管理体系 三.Kerberos协议 1. 用户登录与 AS 请求 2…

WEB安全--内网渗透--利用Net-NTLMv2 Hash

一、前言 在前两篇文章中分析了NTLM协议中Net-NTLMv2 Hash的生成、如何捕获Net-NTLMv2 Hash&#xff0c;现在就来探讨一下在内网环境中&#xff0c;如何利用Net-NTLMv2 Hash进行渗透。 二、Net-NTLM Hash的破解 工具&#xff1a;hashcat 原理&#xff1a;利用其内部的字典对…

如何正确使用 `apiStore` 进行 API 管理

在现代前端开发中&#xff0c;API 管理是一个非常重要的环节。apiStore 是一个基于 Pinia 的状态管理工具&#xff0c;它可以帮助我们更高效地管理和调用 API。本文将详细介绍如何正确使用 apiStore&#xff0c;包括如何创建 API 配置文件、在组件中使用 apiStore 以及如何配置…

瓦片数据合并方法

影像数据 假如有两份影像数据 1.全球底层影像0-5级别如下&#xff1a; 2.局部高清影像数据级别9-14如下&#xff1a; 合并方法 将9-14文件夹复制到全球底层0-5的目录下 如下&#xff1a; 然后合并xml文件 使得Tileset设置到最高级&#xff08;包含所有级别&#xff09;&…

C++中的类和对象(上)

1 类的定义 1.1 类定义的格式 1 class为定义类的关键字&#xff0c;Stack为类的名字&#xff0c;{}中为类的主体&#xff0c;注意类定义结束时后面分号不能省 略》。类体中内容称为类的成员&#xff1a;类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数…

【Tauri2】013——前端Window Event与创建Window

前言 【Tauri2】012——on_window_event函数-CSDN博客https://blog.csdn.net/qq_63401240/article/details/146909801?spm1001.2014.3001.5501 前面介绍了on_window_event&#xff0c;这个在Builder中的方法&#xff0c;里面有许多事件&#xff0c;比如Moved&#xff0c;Res…

【问题处理】webpack4升webpack5,报错Uncaught ReferrnceError: process is not defined

问题 正在做webpack4升webpack5&#xff0c;项目构建项目成功后在浏览器打开时报错 Uncaught ReferrnceError: process is not defined。 原因 webpack 5 不再自动 polyfill Node.js 的核心模块。 如果你在浏览器运行的代码中使用它&#xff0c;需要从 NPM 中安装兼容模块…

软件工程师减肥计划

一、目标设定 在 3 个月内减轻体重 5-7kg&#xff0c;改善身体代谢水平和体脂率&#xff0c;增强身体活力和精神状态&#xff0c;以更好地适应工作强度。 二、饮食调整 &#xff08;一&#xff09;基本原则 控制热量摄入&#xff0c;保证每天摄入热量低于消耗热量 500-800 …

即时访问成为降低风险的关键

云计算和软件即服务 (SaaS) 解决方案的广泛采用从根本上重塑了企业的数字格局。 不同行业的组织越来越多地利用云固有的可扩展性和成本效益来推动创新和简化运营。 这种向基于云的环境的转变也带来了一系列新的复杂安全挑战&#xff0c;需要仔细考虑并制定强有力的缓解策略。…

[环境配置] 1. 开发环境搭建

开发环境搭建 本文档将详细介绍如何搭建深度学习开发环境&#xff0c;包括 Python 环境配置、IDE 选择与配置以及虚拟环境管理。 也会介绍一下最近比较流行的 uv 工具。它是一个用 Rust 编写的极其快速的 Python 包和项目管理工具。 uv 是一个非常强大的工具&#xff0c;它可…

rust 同时处理多个异步任务,并在一个任务完成退出

use std::thread; use tokio::{sync::mpsc,time::{sleep, Duration}, };async fn check_for_one() {// 该函数会每秒打印一次 "write"loop {println!("write");sleep(Duration::from_secs(1)).await;} }async fn start_print_task() -> Result<(), (…

“群芳争艳”:CoreData 4 种方法计算最大值的效率比较(上)

概览 在 CoreData 支持的 App 中&#xff0c;一种常见操作就是计算数据库表中指定字段的最大值&#xff08;或最小值&#xff09;。就是这样一种看起来“不足挂齿”的任务&#xff0c;可能稍不留神就会“马失前蹄”。 在实际的代码中&#xff0c;我们怎样才能既迅速又简洁的…

skynet网络包库(lua-netpack.c)的作用解析

目录 网络包库&#xff08;lua-netpack.c&#xff09;的作用解析1. 数据包的分片与重组2. 网络事件处理3. 内存管理4. 数据打包与解包 动态库&#xff08;.so&#xff09;在 Lua 中的使用1. 编译为动态库2. Lua 中加载与调用(1) 加载模块(2) 核心方法(3) 使用示例 3. 注意事项 …

计科数据库第二次上机操作--实验二 表的简单查询

一、建数据库和表 1&#xff0e;启动数据库服务软件 Navicat 2&#xff0e;在 Navicat 中建立数据库 test 3. 在test数据库上建立teacher表&#xff1a; 二、基本查询 2.1 从teacher表中分别检索出教师的所有信息 SELECT * FROM teacher WHERE 教工号2000; SELECT * FROM t…

WPF依赖注入

一、IOC 在 WPF 中的原理 控制反转&#xff08;IOC&#xff09;是一种设计原则&#xff0c;它将对象的创建和依赖关系的管理从对象本身转移到外部容器&#xff08;IOC 容器&#xff09;。在传统的编程方式中&#xff0c;一个对象如果需要使用另一个对象&#xff08;即存在依赖…

【大模型深度学习】如何估算大模型需要的显存

一、模型参数量 参数量的单位 参数量指的是模型中所有权重和偏置的数量总和。在大模型中&#xff0c;参数量的单位通常以“百万”&#xff08;M&#xff09;或“亿”&#xff08;B&#xff0c;也常说十亿&#xff09;来表示。 百万&#xff08;M&#xff09;&#xff1a;表示…

BUUCTF流量分析题

文章目录 前言wireshark被嗅探的流量被偷走的文件easycap数据包中的线索秘密文件[安洵杯 2019]Attack (难&#xff0c;没写)被劫持的神秘礼物大流量分析&#xff08;一&#xff09;大流量分析&#xff08;二&#xff09;大流量分析&#xff08;三&#xff09;模板模板 前言 CT…

adb检测不到原来的设备List of devices attached解决办法

进设备管理器-通用串行总线设备 卸载无法检测到的设备驱动 重新拔插数据线

mapbox基础,加载栅格图片到地图

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️raster 栅格图层 api二、🍀使用本地载…

复活之我会二分

文章目录 整数二分模板模板1&#xff1a;满足条件的第一个数模板2&#xff1a;满足条件的最后一个数 浮点数二分模板一、Building an Aquarium思路分析具体代码 二、Tracking Segments思路分析具体代码 三、Wooden Toy Festival思路分析具体代码 四、路标设置思路分析具体代码 …