codeforces1559 D2. Mocha and Diana (Hard Version)(并查集+启发式合并+随机化)

D2. Mocha and Diana (Hard Version)

RunningBeef题解
首先将图1的点与1号点所在的连通块相连,图2类似。

然后就是在图1和图2中选择没有和1号点在同一个连通块的点,能连边就连。

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
template <class T=int> T rd()
{T res=0;T fg=1;char ch=getchar();while(!isdigit(ch)) {if(ch=='-') fg=-1;ch=getchar();}while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res*fg;
}const int N=100010;int n,m1,m2;
struct dsu 
{vector<int> fa;dsu(int n):fa(n){iota(fa.begin(),fa.end(),0);}int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}void merge(int x,int y){x=find(x),y=find(y);if(x>y) swap(x,y);fa[y]=x;}
}; 
int main()
{n=rd(),m1=rd(),m2=rd();dsu t1(n+1),t2(n+1);while(m1--){int u=rd(),v=rd();t1.merge(u,v);}while(m2--){int u=rd(),v=rd();t2.merge(u,v);}vector<int> v1,v2;vector<pair<int,int>> ans;for(int i=2;i<=n;i++) {if(t1.find(i)!=1&&t2.find(i)!=1) {ans.push_back({1,i});t1.merge(1, i);t2.merge(1, i);}if(t1.find(i)!=1)v1.push_back(i);if(t2.find(i)!=1)v2.push_back(i);}while(!v1.empty()&&!v2.empty()) {if(t1.find(v1.back())==1&&t2.find(v1.back())==1) {v1.pop_back();continue;}   if(t1.find(v2.back())==1&&t2.find(v2.back())==1){v2.pop_back();continue;}ans.push_back({v1.back(),v2.back()});t1.merge(v1.back(),v2.back());t2.merge(v1.back(),v2.back());v1.pop_back();v2.pop_back();} printf("%d\n",(int)ans.size());for(auto t:ans) printf("%d %d\n",t.first,t.second);
}

Code2

晚上刷b站刷到neal大神,发现这个随机做法很吊,于是写一下,顺便学习下pb_ds

n\color{black}\text nneal\color{red}\text {eal}eal大神的做法

首先将图1连边后变成若干个连通块,同样将图2连边后也变成若干个连通块。
最终能够连边的数量一定是让某个图变成一棵树。于是对于连边的答案数量是固定的。

对于每次连边,我们随机从图一或者图二中随机随机选择某个连通块的某两个点,看看它们是否能够连边,如果能就连上,就这样随机连边。

yy一下感觉每次连边成功的概率非常大。why?

考虑冲突的概率:假设图1中有x个连通块,图2中有y个连通块

不冲突的大致概率1−1x2−1y2+cst1-\frac{1}{x^2}-\frac{1}{y^2}+\text{cst}1x21y21+cst

图一冲突或者图二冲突。
cst\text{cst}cst根据容斥原理在两个图中都冲突的概率。

x或y都必须大于1,于是概率会大于12\frac{1}{2}21,已经比较大了。


需要维护并查集有哪些点,可以用个vector<int> lis维护,合并的时候启发式合并。

维护连通块需要用pb_ds库,我们需要快速find_by_order,并且支持快速插入删除,需要平衡树。

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
using ll=long long;template <class T=int> T rd()
{T res=0;T fg=1;char ch=getchar();while(!isdigit(ch)) {if(ch=='-') fg=-1;ch=getchar();}while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res*fg;
}
template<typename T>
using ordered_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;const int N=100010;int n,m1,m2;
struct dsu 
{vector<int> fa;vector<vector<int>> lis;int cnt; //连通块的数量dsu(int n){fa.resize(n);lis.resize(n);cnt=n-1;for(int i=0;i<n;i++) fa[i]=i,lis[i]={i};}int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}bool merge(int x,int y){x=find(x),y=find(y);if(x==y) return false;if(lis[x].size()<lis[y].size()) swap(x,y);lis[x].insert(lis[x].end(),lis[y].begin(),lis[y].end());lis[y].clear();fa[y]=x;cnt--;return true;}
}; std::mt19937 rnd(233);
int main()
{n=rd(),m1=rd(),m2=rd();dsu t1(n+1),t2(n+1);while(m1--){int u=rd(),v=rd();t1.merge(u,v);}while(m2--){int u=rd(),v=rd();t2.merge(u,v);}int need=min(t1.cnt,t2.cnt)-1;ordered_set<int> rt1,rt2;for(int i=1;i<=n;i++){if(t1.find(i)==i) rt1.insert(i);if(t2.find(i)==i) rt2.insert(i);}// 随机从图中的某个连通块找某个点auto get_random=[&](dsu &t,ordered_set<int> &rt)->int{int u=*rt.find_by_order((rnd()%rt.size()+rt.size())%rt.size());return t.lis[u][(rnd()%t.lis[u].size()+t.lis[u].size())%t.lis[u].size()];};// 随机找一个图auto get_random_node=[&]()->int{if(rnd()%2==0) return get_random(t1,rt1);else return get_random(t2,rt2);};vector<pair<int,int>> ans;while(ans.size()<need){// 随机出两点 a b看看是否能够连边int a=get_random_node();int b=get_random_node();if(t1.find(a)!=t1.find(b)&&t2.find(a)!=t2.find(b)){ans.push_back({a,b});rt1.erase(rt1.find(t1.find(a)));rt1.erase(rt1.find(t1.find(b)));rt2.erase(rt2.find(t2.find(a)));rt2.erase(rt2.find(t2.find(b)));t1.merge(a,b);t2.merge(a,b);rt1.insert(t1.find(a));rt2.insert(t2.find(a));}}printf("%d\n",(int)ans.size());for(auto t:ans) printf("%d %d\n",t.first,t.second);
}

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

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

相关文章

ybtoj祭坛

文章目录冲啊&#xff01;&#xff08;100题祭&#xff09;125题祭140题祭首次登顶&唯一AC150题祭160题祭170题祭冲啊&#xff01;&#xff08;100题祭&#xff09; 2021.4.11 刚好100道 其实是前几天到的&#xff08;忘了是哪一道了。。。&#xff09; 今天写省选题解开了…

牛客题霸 [ 判断一棵二叉树是否为搜索二叉树和完全二叉树] C++题解/答案

牛客题霸 [ 判断一棵二叉树是否为搜索二叉树和完全二叉树] C题解/答案 题解&#xff1a; 搜索二叉树满足以下性质&#xff1a; 1.非空左子树的所以键值小于其根节点的键值 2.非空右子树的所有键值大于其根节点的键值 3.左&#xff0c;右子树都是二叉搜索树 完全二叉树&#x…

CF573D-Bear and Cavalry【动态dp】

正题 题目链接:https://www.luogu.com.cn/problem/CF573D 题目大意 给出nnn个人nnn匹马&#xff0c;每个人/马有能力值wiw_iwi​/hih_ihi​。 第iii个人开始对应第iii匹马&#xff0c;每个人不能选择对应的马&#xff0c;给每个人分配一个马后求最大的∑wihj\sum w_i\times …

C++ __gnu_pbds(hash,可并堆,平衡树)

pb_ds 是GNU-C自带的一个C的扩展库&#xff0c;其中实现了很多数据结构&#xff0c;比STL里面的功能更强大 #include<ext/pb_ds/assoc_container.hpp> #include<ext/pb_ds/tree_policy.hpp> // 用tree #include<ext/pb_ds/hash_policy.hpp> // 用hash #…

理解至上:二叉堆与优先队列详细用法

文章目录二叉堆概述插入代码访问代码完整代码优先队列&#xff1a;priority_queue基本用法小根堆的声明&#xff1a;结构体注意Thanks for reading&#xff01;二叉堆 概述 为什么不用pq呢 算比较简单的数据结构了 它可以用log的时间复杂度插入元素和访问&#xff08;取出&am…

AT5661-[AGC040C]Neither AB nor BA【模型转换】

正题 题目链接:https://www.luogu.com.cn/problem/AT5661 题目大意 一个包含A,B,CA,B,CA,B,C的序列&#xff0c;每次可以选择相邻的两个除了ABABAB和BABABA的删去。 求有多少个长度为NNN的序列可以删完。 1≤N≤1071\leq N\leq 10^71≤N≤107 解题思路 因为每次是删除一个奇…

牛客题霸 [矩阵的最小路径和] C++题解/答案

牛客题霸 [矩阵的最小路径和] C题解/答案、 题目描述 给定一个 n * m 的矩阵 a&#xff0c;从左上角开始每次只能向右或者向下走&#xff0c;最后到达右下角的位置&#xff0c;路径上所有的数字累加起来就是路径和&#xff0c;输出所有的路径中最小的路径和。 题解&#xff…

2021牛客暑期多校训练营7 B-xay loves monotonicity(线段树+不降子序列)

P4198 楼房重建 线段树维护以某点为开头的最长不下降子序列 使用下面calc函数能够计算线段树u维护的区间中&#xff0c;以x为开头最长不下降子序列的个数。 calc需要维护区间最值。 template<typename T> int calc(int u,T x) {if(tree[u].ltree[u].r) return tree[u]…

不止代码:最长上升序列

文章目录题目描述样例解析仔细审题&#xff01;&#xff01;&#xff01;&#xff01;代码题目描述 给定一个序列 求出它的单调上升序列长度并输出这个序列 样例 in: 13 7 9 16 38 24 37 18 44 19 21 22 63 15 out&#xff1a; max8 7 9 16 18 19 21 22 63解析 这题我一开始…

AT2305-[AGC010D]Decrementing【博弈论】

正题 题目链接:https://www.luogu.com.cn/problem/AT2305 题目大意 nnn个数字两个人进行博弈&#xff0c;每个人的操作为 选择一个大于1的数字减一之后所有数字除以所有数字的gcdgcdgcd 无法操作者败&#xff0c;保证初始所有数字互质 求是否先手必胜 1≤n≤1051\leq n\leq…

牛客题霸 [删除链表的倒数第n个节点] C++题解/答案

牛客题霸 [删除链表的倒数第n个节点] C题解/答案 题目描述 给定一个链表&#xff0c;删除链表的倒数第n个节点并返回链表的头指针 例如&#xff0c; 给出的链表为:1->2->3->4->5, n 2. 删除了链表的倒数第n个节点之后,链表变为1->2->3->5. 备注&#xf…

2021牛客暑期多校训练营7 K-xay loves sequence(主席树+二分)

K-xay loves sequence 首先不考虑模kkk的限制&#xff0c;容易想到对原数组做一个差分得到diai−ai−1d_ia_i-a_{i-1}di​ai​−ai−1​&#xff0c;显然对于∀1≤i≤nai0\forall_{1\leq i\leq n} a_i0∀1≤i≤n​ai​0 等价于∀1≤i≤ndi0\forall_{1\leq i\leq n} d_i0∀1≤i…

ASP.NET Core 搭配 Nginx 的真实IP问题

一.前言Nginx&#xff08;Engine X&#xff09;是一个高性能HTTP和反向代理服务&#xff0c;是由俄罗斯人伊戈尔赛索耶夫为访问量第二的Rambler.ru站点&#xff08;俄文&#xff1a;Рамблер&#xff09;开发的&#xff0c;第一个公开版本0.1.0发布于2004年10月4日。 如果…

不止代码:保留道路(ybtoj 最小生成树)

文章目录题目描述解析代码thanks for reading!题目描述 解析 其实就是修建道路 我一开始只能想到枚举g去跑最小生成树 是m^2的算法&#xff08;50pts&#xff09; 但是其实每次加入的边只有一条 而且之前都不在最小生成树上的边以后也肯定不会在 所以可以建一个新的边的集合存…

P7515-[省选联考 2021A卷]矩阵游戏【差分约束】

正题 题目链接:https://www.luogu.com.cn/problem/P7515 题目大意 有一个n∗mn*mn∗m的矩形AAA&#xff0c;然后给出一个(n−1)∗(m−1)(n-1)*(m-1)(n−1)∗(m−1)的矩形BBB满足 Bi,jAi,jAi1,jAi,j1Ai1,j1B_{i,j}A_{i,j}A_{i1,j}A_{i,j1}A_{i1,j1}Bi,j​Ai,j​Ai1,j​Ai,j1​…

牛客题霸 [链表中环的入口节点] C++题解/答案

牛客题霸 [链表中环的入口节点] C题解/答案 题目描述 对于一个给定的链表&#xff0c;返回环的入口节点&#xff0c;如果没有环&#xff0c;返回null 拓展&#xff1a; 你能给出不利用额外空间的解法么&#xff1f; 题解&#xff1a; 判断环有个很巧妙的方法&#xff0c;之…

2021牛客暑期多校训练营8 F-Robots(bitset优化dp)

F-Robots 第一种第二种机器人直接O(n)O(n)O(n)判断即可。 第三种机器人暴力dp&#xff0c;用bitset优化。 bitset<250005> b[i][j] 表示从(i,j)(i,j)(i,j)能到达哪些点&#xff0c;第三种机器人向右向下转移即可。 状态压缩&#xff01; 时间复杂度O(qnn4w)O(qn\frac{…

不止代码:路径数量(ybtoj-最小生成树)

文章目录题目描述解析代码题目描述 解析 乍一看&#xff1a;是个水题啊&#xff01; 显然如果途径存在强连通的点&#xff0c;路径就会变为正无穷 所以缩点加拓扑dp以及一些特判应该就可以解决了&#xff01; 一交&#xff1a;40分。。。 然后就开始拆东墙补西墙的debug。。。…

重磅!!!微软发布.NET Core 2.2

我们很高兴地宣布发布.NET Core 2.2。它包括对运行时的诊断改进&#xff0c;对ARM32 for Windows和Azure Active Directory for SQL Client的支持。此版本中最大的改进是在ASP.NET Core中。ASP.NET Core 2.2和Entity Framework Core 2.2。您可以在Windows&#xff0c;macOS和Li…

Loj#2769-「ROI 2017 Day 1」前往大都会【最短路树,斜率优化】

正题 题目链接:https://loj.ac/p/2769 题目大意 给出nnn个点mmm条地铁线路&#xff0c;每条线路是一条路径。 求111到nnn的最短路且在最短路径的情况下相邻换乘点的距离平方和最大。 1≤n,m,∑si≤1061\leq n,m,\sum s_i\leq 10^61≤n,m,∑si​≤106 解题思路 首先肯定是在…