并查集

POJ 1733(边带权并查集+离散化)

生来就可爱ヽ(ⅴ<●) 提交于 2019-11-28 09:57:10
Parity game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 15492 Accepted: 5876 Description Now and then you play the following game with your friend. Your friend writes down a sequence consisting of zeroes and ones. You choose a continuous subsequence (for example the subsequence from the third to the fifth digit inclusively) and ask him, whether this subsequence contains even or odd number of ones. Your friend answers your question and you can ask him about another subsequence and so on. Your task is to guess the entire sequence of numbers. You suspect some of your friend's

hdu-1243畅通工程(并查集)

泪湿孤枕 提交于 2019-11-28 08:19:01
题意描述: 给出已经建好的路程信息,算出还需要建多少路能使所有的路都能够相通可以通过其他路的转化; 解题思路: 纯属于并查集的模板,算出有多少堆后(有大堆也有小堆),一个路的也可成堆因为他只需要和其他堆的任意一个相连即可; 原文题目: 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路? Input 测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。 注意:两个城市之间可以有多条道路相通,也就是说 3 3 1 2 1 2 2 1 这种输入也是合法的 当N为0时,输入结束,该用例不被处理。 Output 对每个测试用例,在1行里输出最少还需要建设的道路数目。 Sample Input 4 2 1 3 4 3 3 3 1 2 1 3 2 3 5 2 1 2 3 5 999 0 0 Sample Output 1 0 2 998 AC代码: # include <stdio.h> # include <string.h> int f [

【并查集】关押罪犯

江枫思渺然 提交于 2019-11-28 07:16:45
【并查集】关押罪犯 #include <bits/stdc++.h> using namespace std; const int maxn=20010; const int maxm=100010; struct node { int x,y,w; bool operator<(const node &b)const { return w>b.w; } }a[maxm]; int f[maxn*2]; int n,m; int getfa(int x) { return x == f[x] ? x : f[x] = getfa(f[x]); } void merge(int x,int y) { int xx = getfa(x), yy = getfa(y); if (xx != yy) f[xx] = y; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n * 2; i++) { f[i] = i; } for (int i = 1; i <= m; i++) { scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].w); } sort(a + 1, a + 1 + m); for (int i = 1; i <= m; i++) { if (getfa(a[i].x) ==

【畅通工程 HDU - 1232 】【并查集模板题】

℡╲_俬逩灬. 提交于 2019-11-28 06:26:03
并查集讲解和模板 有一个博文对此分析的很透彻,附 链接 为避免原链接失效,现摘录如下: 为了解释并查集的原理,我将举一个更有爱的例子。 话说江湖上散落着各式各样的大侠,有上千个之多。他们没有什么正当职业,整天背着剑在外面走来走去,碰到和自己不是一路人的,就免不了要打一架。但大侠们有一个优点就是讲义气,绝对不打自己的朋友。而且他们信奉“朋友的朋友就是我的朋友”,只要是能通过朋友关系串联起来的,不管拐了多少个弯,都认为是自己人。这样一来,江湖上就形成了一个一个的帮派,通过两两之间的朋友关系串联起来。而不在同一个帮派的人,无论如何都无法通过朋友关系连起来,于是就可以放心往死了打。但是两个原本互不相识的人,如何判断是否属于一个朋友圈呢? 我们可以在每个朋友圈内推举出一个比较有名望的人,作为该圈子的代表人物。这样,每个圈子就可以这样命名“中国同胞队”美国同胞队”……两人只要互相对一下自己的队长是不是同一个人,就可以确定敌友关系了。 但是还有问题啊,大侠们只知道自己直接的朋友是谁,很多人压根就不认识队长要判断自己的队长是谁,只能漫无目的的通过朋友的朋友关系问下去:“你是不是队长?你是不是队长?”这样,想打一架得先问个几十年,饿都饿死了,受不了。这样一来,队长面子上也挂不住了,不仅效率太低,还有可能陷入无限循环中。于是队长下令,重新组队。队内所有人实行分等级制度,形成树状结构,我队长就是根节点

并查集

泄露秘密 提交于 2019-11-28 06:10:14
并查集是一种用于处理一些不相交 集合 (Disjoint Sets)的合并及查询问题的树形数据结构,可以高效的解决多个元素的集合应用问题中: 合并集合、查询某元素属于某集合的问题 并查集的基本函数: 初始化: 1 void init()//未进行操作时没一个元素的祖先的是他自己 2 { 3 for (int i = 1; i <= n; i++) 4 f[i] = i; 5 } 查找: 1 int find(int x)//如果还没有查找到根节点(f[x]==x) 2 { //就不断递归查找x的祖先的祖先(f[x]=find(find[x])) 3 return f[x] == x ? x : f[x] = find(f[x]); 4 } 合并: 1 void merge(int a, int b) 2 { 3 int x = find(a); 4 int y = find(y); 5 if (x != y) 6 f[y] = x; 7 } 基础并查集: 例题: 洛谷 P1551 亲戚 1 #include<iostream> 2 using namespace std; 3 const int maxn = 100010; 4 int n, m, p, f[maxn]; 5 void init() 6 { 7 for (int i = 1; i <= n; i++) 8 f[i]

CodeForces722C

断了今生、忘了曾经 提交于 2019-11-28 05:42:58
CodeForces722C 其实这个题我是不大会的....我一直在想怎么正面突破,然后我就冇了. 康了康 \(dalao\) 们的做法,发现这个题反着做是个很简单的题. 你考虑把删除操作换成倒着加入,然后就变成了一个序列合并问题. 每次加入一个数,只需要向左向右分别判断是否已经加入过数字, 如果加入过,就合并两个并查集,否则什么都不做. 同时维护一下并查集的权值——区间和.(体现在并查集上是子树和.) 最后倒序输出答案即可,不要忘记最后全部删除完成之后是 \(0\) . #include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <queue> #include <map> #define int long long using std::max ; const int N = 1e5 + 100 ; int n , v[N] , p[N] , ans[N] , f[N] , s[N] , maxx , cnt ; inline int getf (int x) { return f[x] == x ? x : f[x] = getf ( f[x] ) ; } signed main () { scanf ("%lld" , &

POJ 1456(贪心,并查集)

为君一笑 提交于 2019-11-28 05:37:01
Supermarket Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 21651 Accepted: 9579 Description A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold by a deadline dx that is measured as an integral number of time units starting from the moment the sale begins. Each product takes precisely one unit of time for being sold. A selling schedule is an ordered subset of products Sell ≤ Prod such that the selling of each product x∈Sell, according to the ordering of Sell, completes before the deadline dx or just when dx expires. The profit of the

学习笔记 带权并查集

老子叫甜甜 提交于 2019-11-28 05:32:16
今天的蒟蒻Lbmttw_lx又要学习新的有趣的东西了! . 最近考的NOIP基础知识里面涉及到了一个比较有趣的东西,叫做带权并查集,可是Lbmttw_lx并不知道是什么,所以今天痛下决心好好学一下 正文分割线   理解权值并查集我们首先需要知道并查集是什么,在这里简单说一下吧   普通并查集的主要作用是判断图是否连通,即两个节点之间是否存在某种联系(即同一个根节点),如下图所示就是一个很普通的并查集,只能看到边代表着方向额而没有记录其他信息    代码应该都会写,不上了   但是有些时候我们需要判断更多的信息,比如把多个连通的图合并为一个图并且记录合并后节点的个数,我们就需要一个更为高级的结构,权值并查集   如何理解这个权值呢?这个权值的意思就是需要额外记录一些信息。      基于对并查集的理解,我们会发现一个比较有趣的事情,就是   看上面的图,我们对C进行find操作,让c连上A,不过在此之前,C会先找到B,然后才连上A,我们可不可以直接把C和A相连呢,这样极大程度上缩小了时间复杂度,得到的结果如下   这种优化有一个学名,叫做并查集的路径压缩,将每一个节点直接与其find操作得到的节点连接。   很轻松的可以写出这样的代码 1 int find(int x) 2 { 3 if (x != f[x]) 4 { 5 f[x] = find(f[x]); 6 } 7

并查集

一世执手 提交于 2019-11-28 02:43:37
并查集的以下几种优化和类型。 1.路径压缩 1 int pre[maxv]; 2 void init(int n) 3 { 4 /*初始化w*/ 5 for (int i= 0; i<= n; i ++) pre[i]= i; 6 } 7 int findFa(int x) 8 { 9 /*寻找树的根节点,并路径压缩w*/ 10 if (pre[x]== x) return x; 11 return pre[x]= findFa(pre[x]); 12 } 13 void join(int x, int y) 14 { 15 /*把x 所在的树并在y 所在的树的根节点下w*/ 16 pre[findFa(x)]= findFa(y); 17 } 2.按秩合并 1 int pre[maxv]; 2 int _rank[maxv]; 3 void init(int n) 4 { 5 for (int i= 0; i<= n; i ++) pre[i]= i; 6 for (int i= 0; i<= n; i ++) _rank[i]= 1; 7 } 8 int findFa(int x) 9 { 10 /*寻找树的根节点,并路径压缩w*/ 11 if (pre[x]== x) return x; 12 return pre[x]= findFa(pre[x]); 13 } 14

Leetcode-并查集

左心房为你撑大大i 提交于 2019-11-28 01:41:13
200.岛屿数量 https://leetcode-cn.com/problems/number-of-islands/ 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。 示例: 输入: 11000 11000 00100 00011 输出: 3 解: 1. 转换为染色问题: 遍历所有节点   if node ==1:     count ++; 将node附近陆地节点赋0   else:     continue 问题,将node附近陆地节点赋0,如何实现? dfs,bfs dfs 实现,递归自然的提供栈 class Solution: def numIslands(self, grid: List[List[str]]) -> int: if not grid or not grid[0]: return 0 self.dx = [-1, 1, 0, 0] self.dy = [0, 0, -1, 1] # 便于向四周扩散,先定义好(dx, dy),左、右、下、上 self.max_x, self.max_y = len(grid), len(grid[0]) # 两个边界 self.grid = grid # 便于传参 self.visited