随笔分类 -  并查集

摘要:给定N个物种的基因序列,若俩个序列s1和s2的最长公共子串长度len满足 |s1|*p<len && |s2|*p<len (p是题目给定的百分比),则俩个物种属于同一类,问这N个物种可以分为几类分析:额,LCS+并查集View Code #include<iostream>#include<algorithm>#include<string>#include<vector>using namespace std;const int N = 100+10;int n,f[N];double p;char str[N][ 阅读全文
posted @ 2012-04-09 19:18 枕边梦 阅读(217) 评论(0) 推荐(0)
摘要:题意:有 n 个数,你不知道它们的值, 然后又有 m 行数,每行 a ,b ,c,表示 a 到 b 之间所有数的和为c(包含了第a个和第b个数)。但是这m行数里面有些是错的,就是与前面给的条件相冲突的,要求你最后输出错了几行。分析:用并查集,同样,还是需要一个辅助数组r[]记录每一个点跟根节点的关系。首先我们可以把问题稍微转化一下,就是如果已知[3,6],[7,10]俩个区间内各自所有数的和,那么就可以[3,10]内所有数的和,可是,这俩个区间根本就不衔接,所有要稍微处理一下,将左区间值减1,就变成了[2,6],[6,10],这样就方便处理了。既然这样的话,[2,6]区间内所有数的和就完全可以 阅读全文
posted @ 2012-02-24 12:29 枕边梦 阅读(1355) 评论(0) 推荐(1)
摘要:比较基础的并查集,求集合所含元素的个数,中间用字典树给出现过的名字标号View Code #include<iostream>#include<algorithm>#include<string>#define MAXN 100000+10using namespace std;int f[MAXN],r[MAXN],n,num;typedef struct node{ int cnt; struct node *next[52];}*tree,Trie;tree root; inline int GetNum(char *t)//用字典树对字符串编号{ t 阅读全文
posted @ 2012-02-22 20:32 枕边梦 阅读(242) 评论(0) 推荐(0)
摘要:题意:给你1~n个城市每个城市有一个球编号与城市编号相同,现在又两种操作1.T X Y 把x球所在城市的所有球转移到y球所在的城市。2.Q X 求出X球所在的城市编号 城市中球的总数 X球移动的次数思路:这题明显的并查集,很好的一道题,其关键在于如何记录球移动次数。当一个球从一个城市移到另一个城市之后,那么“之后”被转移的次数就等于他的直接父节点的转移次数,而经过一次路径压缩之后,实际上他已经被接到根节点后面了,值得注意的一点是,当前,如果一个点是根节点,那么他的转移次数一定是0。View Code #include<iostream>#include<algorithm&g 阅读全文
posted @ 2012-02-15 20:20 枕边梦 阅读(173) 评论(0) 推荐(0)
摘要:题意:对每一个提问,求出第K条线段所在集合的线段数。所以相交的线段属于同一个集合分析:几何+并查集View Code #include<iostream>#include<algorithm>#include<string>#include<math.h>#define MAXN 1000+10 using namespace std;struct Point{ double x,y;};struct seg{ Point a,b;}se[MAXN];int n,m,f[MAXN],r[MAXN];void init(){ for(int i=0 阅读全文
posted @ 2012-02-15 16:47 枕边梦 阅读(234) 评论(0) 推荐(0)
摘要:题意:给定n个点,刚进行两种操作,将两个点合并,以及将一个点孤立,问最后点有几堆分析:删除一个点,只是将该点独立起来,或者说将该点从所在集合中脱离,而所在集合的结构不变,若真的将该点从集合中删去,会带来很多不必要的麻烦,所以,可以反而添加一个虚拟的点代替独立出来的点,这样,用一个数组将每一个点都映射到一个虚拟的点上,之后在虚拟的点上面操作即可。当要独立一个点时,只需将该点映射到另一个原先不存在的点即可。之后,统计集合个数有俩种方法,一个是根据集合含有的元素的个数,另一个则是统计根节点的个数。其一#include<iostream>#include<algorithm># 阅读全文
posted @ 2012-02-14 20:14 枕边梦 阅读(980) 评论(0) 推荐(0)
摘要:中文题,题意就不说了不过想不到并查集这样用对于题目中的路,按速度进行排序,这样,如果从第 i 条路到第 j 条路之间的所有路能够让 i 和 j 连通,那么,这就存在一条路,且这条路的舒适度就是 两者的差值。 这样,只要枚举从每一条路开始,向前找到可以使得 起点和终点连通的路的舒适度,就可以找到答案了View Code #include<iostream>#include<algorithm>using namespace std;struct edge{ int u,v,w;}e[1001];int f[201],n,m;bool cmp(edge a,edge b){ 阅读全文
posted @ 2012-02-13 21:17 枕边梦 阅读(1100) 评论(0) 推荐(0)
摘要:题意:对当前的一个图,求一个最大的伪森林,即边权值最大,每一个连通分量至多含有一个圈的森林。分析:类似于求一个最大生成树,先将边权值排序,之后就是一个加边合并的过程,俩点所在边可以加入到当前集合有俩个条件:1.两点在两个集合,且有至少一个集合没有环2.两点在一个集合,且这个集合没有环hdu3367#include<iostream>#include<algorithm>using namespace std;struct edge{ int u,v,c;}e[100005];int f[10005],n,m;bool ee[100005],ff[10005];__int 阅读全文
posted @ 2012-02-09 22:19 枕边梦 阅读(404) 评论(0) 推荐(1)
摘要:呵呵,基本的并查集,合并之后,判断集合的个数即可#include<iostream>#include<algorithm>#define maxn 1010using namespace std;int f[maxn],n,m;void init(){ for(int i=0;i<maxn;i++) f[i]=i;}int find(int x){ if(x==f[x]) return x; f[x]=find(f[x]); return f[x];}//路径压缩void Union(int x,int y){ int a=find(x); int b=find( 阅读全文
posted @ 2011-11-05 22:21 枕边梦 阅读(356) 评论(0) 推荐(0)
摘要:题意:题目将以这样的形式进行提供已知条件或者提问,分析:首先可以想到的是可以用并查集来做。题目的是x1^x2^x3^……式子的值,那么首先就要考虑俩个问题了:1):如何记录x[]元素之间的关系2):怎样传递元素之间的关系这里我们注意到异或运算的性质:对于a,b,c有:a xor b == c 和 a xor c == b 和 b xor c == a 等价,a^a==0因此:我们用r[]数组保存该元素与根节点异或运算的关系;接下来,为了方便处理,我们定义一个虚点xn,r[xn]=0,这样,只要根节点为xn的元素,这对于的具体也是已知的,同时,r[]的值就是其具体的值;而且,有一个好处就是,当进 阅读全文
posted @ 2011-10-22 10:05 枕边梦 阅读(1051) 评论(0) 推荐(0)
摘要:题意:我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张“幸运爱尔兰”(一种彩票)。结果这张彩票让他获得了这次比赛唯一的奖品——坐落于爱尔兰郊外的一座梦幻般的城堡! 喜欢吹嘘的农夫约翰立刻回到有着吹嘘传统的威斯康辛老家开始吹嘘了, 农夫约翰想要告诉他的奶牛们关于他城堡的一切。他需要做一些吹嘘前的准备工作:比如说知道城堡有多少个房间,每个房间有多大。另外,农夫约翰想要把一面单独的墙(指两个单位间的墙)拆掉以形成一个更大的房间。你的工作就是帮农夫约翰做以上的准备,算出房间数与房间的大小。 城堡的平面图被划分成M*N(1 <=M 阅读全文
posted @ 2011-10-21 07:28 枕边梦 阅读(220) 评论(0) 推荐(0)
摘要:只要最后统计出有多少个集合就好了我用并查集还有set做的,好像用set慢了一点#include<stdio.h>#include<set>using namespace std;int f[1010];int find(int x){ if(x==f[x]) return f[x]; f[x]=find(f[x]); return f[x];}void Union(int x,int y){ int a=find(x); int b=find(y); if(a==b) return ; f[a]=b; return ;}int main(){ int n,m,i; in 阅读全文
posted @ 2011-05-20 22:25 枕边梦 阅读(184) 评论(1) 推荐(0)
摘要:这题的话,跟食物链很相识,也是有三类,所以那个公式的话,还是一样的题意是要找出里面唯一的一个judge,judge的特别就是他没有固定属于哪一类,所以只能枚举每一个人当judge的情况了满足是唯一的judge的条件:1)当然就是枚举完所有人,只有一个的时候,那就是唯一的了;2)当此人是judge时,所有语句都成立,即不发生冲突在这里题目还要出输出,在第几行判断该人是judge的,这个也蛮好理解的,此人之前的所有人作为judge时出现矛盾的行数的最大值就是就是我们判断的依据,其实也可以这样想,判断当前面所以人不能成为judge的行数的最大,就是我们判断此人为judge的行数当不止一个人可以成为j 阅读全文
posted @ 2011-05-12 12:23 枕边梦 阅读(202) 评论(0) 推荐(0)
摘要:这题目让我郁闷了好久的说,首先就是离散化过程,区间大小和测试的例子相差太大,十分有必要进行离散化,这里就出现一个问题了,这道题目而已,离散化过程需要保持数据之间的相对大小吗?需要跟不需要相差很多吗?差别的话,当然很大啦,如果不需要保持数据的相对大小,那么,在映射过程中就可以直接将映射值放入运算了,而如果需要呢?这时,我们需要先将读入的数据保存,再排序,进入hash,或者使用map函数,这一过程就用了好多内存了和时间了为什么不需要保持数据的相对大小呢?因为我们用的是并查集,每个节点都有一个根节点,这里就是关键了,根节点是如何选的呢?呵呵,其实仔细想想,我们如何判断一个区间内1 的个数的奇偶性呢? 阅读全文
posted @ 2011-05-11 21:46 枕边梦 阅读(771) 评论(0) 推荐(0)
摘要:悲剧呀,我怎么又理解错题意了,写了一个代码,固执的修改提交,都WA了俩次首先是一种贪心的思想,题意是要求利用table中给的商品利润和有卖出的期限,计算最大的获利,你可以认为是这样,一个时间只能售出一件商品,但题目中给你的是期限,不是具体哪一天卖出,(我的问题就在这里了),就是把能在期限之前卖出的商品卖出,累加利润,当然,只能在同一天卖出的商品,当然是选择其中利润最大的一件,所以,首先就要对商品的利润进行排序啦,也就是所谓的贪心,首先选择利润最大的,而且最晚卖出,所谓的最晚,就是在最接近期限,而且还没被占用的时间,这里说到了“占用”,也到了并查集出场了这里关于并查集的应用很巧妙,父节点记录的就 阅读全文
posted @ 2011-05-09 21:32 枕边梦 阅读(1109) 评论(0) 推荐(1)
摘要:呵呵,这道题目的话,跟之前那道计算路径程度有点区别给你多个路径,让你求出哪些节点被作为最近公共祖先,并计算被作为最近公共祖先的次数首先,读入数据有点麻烦,按代码中那种方法,还蛮方便的其次就是,需要找出根节点,再进行深度优先搜索,这是很求路径长度唯一的区别,计算路径的时候,从任意节点开始,并不影响计算路径的长度但是,此题目中,我们要保证每一个最近公共祖先都是正确的,为什么这么说呢?因为,在计算路径的时候,其实只是一种相对的情况,即,这已遍历的节点中,相对的某个节点是最近公共祖先,没有一种严格性而此题就是要求最近公共祖先,所以必须先找出根节点,即入度为零的节点,这个也很好理解具体的,见之前的258 阅读全文
posted @ 2011-05-08 23:06 枕边梦 阅读(337) 评论(0) 推荐(0)
摘要:今天效率还不错,再接再厉^-^总得来说,这道题目不难,但悲剧的是,我一开始理解错题意了题意:1)n个队列,n个立方体。 2)初始化时候每个队列有一个立方体。 3)两个操作:m x y:将x所在的集合放到y所在的集合里面,说白了,就是将y所在集合放到x所在集合后面 c x:问x立方体下面有多少个立方体呵呵,发现,其实,每次“真正”执行find()的时候,实际上都是对Union的进一步维护,只有进行一次与节点x有关的Union时,才会对x维护,而且,维护过后,x节点之上的节点也会同时被维护,并且直接挂到根节点上,这意味着之后对另一些点的维护并不会影响到已维护了的节点还有就是那个计算,节点x之下的元 阅读全文
posted @ 2011-05-08 20:54 枕边梦 阅读(259) 评论(0) 推荐(0)
摘要:这题呢,还好吧,主要是在求相对坐标的时候,有点抽象,不过还是可以理解的,画个坐标对一对就知道了还有就是,并查集的应用,因为要在某一个查询位置判定该点是否已经知道具体坐标,问题转化为俩点是否属于同一个集合,属于同一个集合,则相对于根节点的坐标都知道了,直接求曼哈顿距离,否则无法求出距离代码中附带了解释:#include<stdio.h>#include<string.h>#define MAXN 40010int n,m,k;struct node{ int x,y,f;}f[MAXN];struct node1{ int a,b,d; char ch;}e[MAXN]; 阅读全文
posted @ 2011-05-08 16:50 枕边梦 阅读(247) 评论(0) 推荐(0)
摘要:这题目跟杭电的2586很像,呵呵,应该说,本来这道是先做的,但是LAC不会,所以就先做了那道基础题好悲剧呀,在代码里面加了一个测试输出,结果忘记删了,还固执的贡献了几个WA,题目中给的方向是没用的,读进来就可以因为代码基本一样,具体解释见hdu2586#include<stdio.h>#include<string.h>#include<stdlib.h>#define MAXN 40010struct node{ int vex,next,dis;}g[MAXN*2],q[10010*2];int f[MAXN],first[MAXN],head[MAXN 阅读全文
posted @ 2011-05-08 13:14 枕边梦 阅读(158) 评论(0) 推荐(0)
摘要:View Code #include <iostream> #define MAXN 40010 using namespace std ; struct Graph { int vex , next , dis ; }; Graph g[MAXN * 2] , Q[400] ; int first[MAXN] , head[MAXN] , set[MAXN] , away[MAXN] , n , m ; bool visited[MAXN] ; //first[v]用来查找节点所在边,即g[first[v]],同时, g[i].next记录与节点v连接的节点,这俩个记录十分的关键 阅读全文
posted @ 2011-05-08 11:35 枕边梦 阅读(1213) 评论(0) 推荐(0)