《算法竞赛·快冲300题》每日一题:“小球配对”

算法竞赛·快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。
所有题目放在自建的OJ New Online Judge。
用C/C++、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。

文章目录

  • 题目描述
  • 题解
  • C++代码
  • Java代码
  • Python代码

小球配对” ,链接: http://oj.ecustacm.cn/problem.php?id=1850

题目描述

【题目描述】 给定n个小球,编号为1-n,给定m个篮子,编号为1-m。
  每个球只允许放入特定的两个篮子其中的1个。
  每个球必须放入某个篮子。
  如果篮子中球的数量为奇数,则该篮子是特殊的。
  计算特殊的篮子最少有多少个。
【输入格式】 第一行为两个正整数n和m,1≤n,m≤200000。
  接下来n行,每行两个数字Ai,Bi,表示第i个球可以放入Ai或者Bi编号的篮子。
  1≤Ai,Bi≤m,Ai≠Bi。
【输出格式】 输出一个数字表示答案。
【输入样例】

4 3
1 2
2 3
1 3
1 2

【输出样例】

0

题解

  n个球放到m个篮子里,最暴力的方法是把所有可能的放法列出来,然后看特殊篮子最少的那种方法。可以用DFS编码找所有可能的排列,但显然超时。
  读者也可能想过用DP,从第一个球开始逐个往篮子里放小球,同时计算最少的特殊篮子,直到放完所有的小球。但DP转移方程似乎写不出来。
  其实本题是一个简单的图问题。把篮子看成图上的点;一个球连接两个篮子,可以把球看成连接点的线。这样,篮子和球就分别抽象为点和线,所有的篮子和球构成了一个图,其中有些点是连通的,有些不连通。一个连通子图上的点,最少有多少个是特殊篮子?很容易证明,如果这个子图的线条是偶数个,则特殊篮子最少为0个;如果子图的线条有奇数个,则特殊篮子最少是1个。请读者自己证明。
  本题这样编程:用并查集合并篮子和球,构成多个连通子图;每个连通子图是一个并查集;在合并2个集时,用并查集的根记录这个连通子图的总线条数量。代码只对每个球(线条)进行了并查集合并操作,一次合并为O(1),n次合并的总复杂度为O(n)。
【重点】 并查集的应用。

C++代码

  一定要用带路径压缩的并查集,一次合并的复杂度才是O(1)的。

#include<bits/stdc++.h>
using namespace std;
const int N = 200005;
int n,m,f[N],s[N],vis[N];      //s是并查集,f[i]是点i上的线条数量
int find(int x){               //并查集的查询,带路径压缩if(x!=s[x]) s[x] = find(s[x]);return s[x];
}
void merge(int x, int y){      //合并int p = find(x), q = find(y);if (p!=q){                  //原来不属于一个集合s[p] = s[q];            //并查集合并f[q] += f[p]+1;         //用并查集的根记录这个连通子图的线条总数}else f[p]++;                //用并查集的根记录这个连通子图的线条总数
}
int main(){scanf("%d%d",&n,&m);for (int i=1;i<=m;i++) s[i]=i;  //初始化并查集for (int i=1;i<=n;i++)    {int x,y;   scanf("%d%d",&x,&y);merge(x,y);}int ans = 0;for (int i=1;i<=m;i++){int x = find(i);           //查找有多少个集if (!vis[x]) {             //集x还没有统计过if (f[x] & 1)  ans++;  //集x的线条总数是奇数,答案加1vis[x] = 1;       }}printf("%d",ans);return 0;
}

Java代码

import java.util.Scanner;public class Main {static int N = 200005;static int n,m;static int[] f = new int[N];     //f[i]是点i上的线条数量static int[] s = new int[N];      //s是并查集static int[] vis = new int[N];public static void main(String[] args) {Scanner scan = new Scanner(System.in);n = scan.nextInt();m = scan.nextInt();for (int i = 1; i <= m; i++) s[i] = i;    //初始化并查集for (int i = 1; i <= n; i++) {int x = scan.nextInt(), y = scan.nextInt();merge(x, y);}int ans = 0;for (int i = 1; i <= m; i++) {int x = find(i);                      //查找有多少个集if (vis[x] == 0) {                    //集x还没有统计过if ((f[x] & 1) == 1) ans++;       //集x的线条总数是奇数,答案加1vis[x] = 1;}}System.out.println(ans);scan.close();}static int find(int x) {                       //并查集的查询,带路径压缩if (x != s[x]) s[x] = find(s[x]);return s[x];}static void merge(int x, int y) { //合并int p = find(x), q = find(y);if (p != q) {                              //如果原来不属于一个集合s[p] = s[q];                           //并查集合并f[q] += f[p] + 1;                      //用并查集的根记录这个连通子图的线条总数}else f[p]++;                 //用并查集的根记录这个连通子图的线条总数}
}

Python代码

  注意用setrecursionlimit扩栈,因为find()是递归函数。

import sys
sys.setrecursionlimit(1000000)
N = 200005
n, m = map(int, input().split())
f, s, vis = [0] * N, [0] * N, [0] * N     # s是并查集,f[i]是点i上的线条数量
def find(x):                              # 并查集的查询,带路径压缩if x != s[x]:   s[x] = find(s[x])return s[x]
def merge(x, y):                          # 合并p, q = find(x), find(y)if p != q:                            # 如果原来不属于一个集合s[p] = s[q]                       # 并查集合并f[q] += f[p] + 1                  # 用并查集的根记录这个连通子图的线条总数else:  f[p] += 1                      # 用并查集的根记录这个连通子图的线条总数
for i in range(1, m + 1):   s[i] = i      # 初始化并查集
for i in range(1, n + 1):x, y = map(int, input().split())merge(x, y)
ans = 0
for i in range(1, m + 1):x = find(i)                           # 查找有多少个集if not vis[x]:                        # 集x还没有统计过if f[x] & 1: ans += 1             # 集x的线条总数是奇数,答案加1            vis[x] = 1
print(ans)

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

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

相关文章

Triton_server部署学习笔记

下载镜像 docker pill http://nvcr.io/nvidia/tritonserver:22.07-py3 docker run --gpus all -itd -p8000:8000 -p8001:8001 -p8002:8002 -v /home/ai-developer/server/docs/examples/model_repository/:/models nvcr.io/nvidia/tritonserver:22.07-py3 docker exec -it a5…

Spring+SpringMvc+Mybatis整合小Demo

原始方式整合SSM 不使用spring-mybatis包 项目内容 整合ssm完成对account表新增和查询的操作 项目大体结构 创建mavenWeb项目 pom文件中引入依赖 spring核心、aspectj(aop)、spring-jdbc(jdbcTemplate)、spring-tx(事务)、 数据源&#xff1a;mysql、c3p0、mybatis my…

JVM 参数配置规范

废话不说&#xff0c;直接上干货&#xff01;&#xff01;&#xff01; JVM 规范&#xff1a; 参数备注/参数释义交易规范JVM版本1.8.0_60以下&#xff0c;无法使用Pfinder 1.8.0_131之前&#xff0c;jvm无法感知docker的真实核数和内存大小&#xff0c;而是使用的宿主机的核…

vue2的 element 表格单元格合并

<template><div><el-table show-summary :summary-method"getSummaries" :span-method"objectSpanMethod" :data"tableData" row-key"id" ref"tableDom" border><el-table-column label"序号&quo…

Zookeeper集群下载安装并启动

前提&#xff1a;准备三台虚拟机 集群启动修改配置&#xff08;3台服务器都要执行&#xff09; 1、下载Zookeeper安装包 Zookeeper的下载地址&#xff1a; https://zookeeper.apache.org/releases.html https://archive.apache.org/dist/zookeeper 2、上传Zookeeper安装包 …

【NLP】小项目:基于transformer的文本摘要

一、说明 本博客的主要焦点是使用“变压器”的非常高级的接口,即拥抱面管道。使用此界面,您将看到我们只需 1 或 2 行代码即可总结文本。 回顾什么是文本摘要以及我们在哪里使用它。如何使用拥抱面转换器执行文本摘要(只需几行代码)二、什么是文本摘要? 文本摘要是将大型文…

【golang】12、gin 源码解析

文章目录 快速使用返回响应路由匹配pathqueryMultipart/Urlencoded Form 解析请求MultipartFrom MiddleWare github.com/gin-gonic/gin 是 golang 的 web 框架&#xff0c;其用字典树做路由匹配、支持中间件&#xff0c;本文介绍其源码实现。 快速使用 package mainimport (&…

ylb-接口6验证手机号是否注册

总览&#xff1a; 1、service处理 在api模块下service包&#xff0c;创建一个UserService接口&#xff1a;&#xff08;根据手机号查询数据queryByPhone(String phone)&#xff09; package com.bjpowernode.api.service;import com.bjpowernode.api.model.User; import co…

ASL/CS系列音视频转换方案芯片,Typec拓展坞方案芯片

音视频单转方案芯片&#xff1a; CS5565 Typec转HDMI 8K 60HZ转换方案 可替代RTD2173 PS196 CS5801 HDMI转eDP/DP方案 可替代LT6711 CS5212 DP转VGA转换方案 可PIN TO PIN 替代RTD2166 CS5211 E…

❤️创意网页:HTML5 Canvas技术实现绚丽多彩的烟花特效

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;欢迎踏入…

【java】【基础2】程序流程控制

目录 一、最经典的三种执行顺序 二、分支结构 2.1 if 2.2 switch 2.3 if与switch区别 三、循环结构 3.1 for循环 3.2 while循环 3.3 do-while循环 3.4 三种循环区别 3.5 补充知识&#xff1a;死循环 3.6 补充知识&#xff1a;循环嵌套 四、跳转关键字&#xff1a;br…

Mysql如何查询出两个日期之间的所有日期?

问题&#xff1a; 有时我们在生成一些时间轴类似的数据时&#xff0c;要求数据库不管有没有指定天的数据&#xff0c;都要生成该时间节点&#xff0c;可用mysql.help_topic来解决此类问题&#xff0c;通过序列和日期函数相结合来满足我们的业务需求。 例如&#xff1a;查询20…

spring启动一下就停止了

spring启动一下就停止了。 这个问题比较简单&#xff0c;百度了下&#xff0c;还是有些人问&#xff0c;记录下吧。 是因为没有引入spring-boot-starter-web包&#xff0c;或者该包没有生效。 有时spring-boot-starter-parent版本不对&#xff0c;就可能没生效&#xff0c;写明…

LeetCode | C++ 动态规划——123.买卖股票的最佳时机III 、188.买卖股票的最佳时机IV

目录 123.买卖股票的最佳时机III188.买卖股票的最佳时机IV 123.买卖股票的最佳时机III 123题目链接 根据题意&#xff1a;最多可以完成 两笔 交易&#xff0c;即可以买卖股票一次&#xff0c;可以买卖两次&#xff0c;也可以不买卖 dp数组定义&#xff1a; 此时 一天就有五个…

Web开发的富文本编辑器CKEditor介绍,Django有库ckeditor_uploader对它进行支持,django-ckeditor安装方法及使用注意事项

当需要在网页应用程序中提供富文本编辑功能时&#xff0c;CKEditor是一个流行的选择。CKEditor是一个开源的JavaScript富文本编辑器&#xff0c;它提供了强大的功能和用户友好的界面&#xff0c;使用户可以轻松创建和编辑格式化的文本内容。 以下是CKEditor的一些主要特性&…

kakfa 2.4.1 java的生产者client在发送消息前分配消息属于哪个分区源码

标题是否不是很熟悉&#xff0c;面试不得必问啊 KafkaProducer 1、客户端暴露出来可以让开发人员调用的发送消息的方法send2、send实际调用私有方法doSend获取集群信息(并且得到这条数据写哪个分区)2.1获取kafka服务端集群某个topic的元数据方法waitOnMetadata2.2根据消息是否指…

rabbitMQ杂记

消息队列应用场景 消息队列中间件是分布式系统中重要的组件&#xff0c;主要解决应用耦合&#xff0c;异步消息&#xff0c;流量 削锋等问题实现高性能&#xff0c;高可用&#xff0c;可伸缩和最终一致性&#xff1a; 解耦&#xff1a; 异步&#xff1a; 削峰&#xff1a; 常…

再见RestTemplate,Spring 6.1新特性:RestClient 了解一下!

在最近发布的Spring 6.1 M2版本中&#xff0c;推出了一个全新的同步HTTP客户端&#xff1a;RestClient。用一句话来让Spring开发者认识RestClient的话&#xff1a;像WebClient一样具备流畅API的RestTemplate。 所以&#xff0c;RestClient的使命就是淘汰已经有14年历史的RestTe…

实习经历总结

写在前面&#xff1a; 临毕业前突发奇想打算找实习&#xff0c;由于准备不是很充分加上没有经验&#xff0c;海投了一些岗位&#xff0c;方向主要是测试开发&#xff0c;base主要是北京&天津。 一些公司的面试&#xff1a; 当时投了很多大厂&#xff0c;美团&#xff0c…

elasticsearch高级功能之跨集群复制CCR

CCR的作用(Cross-Cluster Replication&#xff0c;跨集群复制)常用的场景如何使用工作原理源码分析 CCR的作用(Cross-Cluster Replication&#xff0c;跨集群复制) CCR功能允许用户在不同的Elasticsearch集群之间同步索引数据。这对于实现跨集群复制、数据备份、灾难恢复和多数…