hud 2473 Junk-Mail Filter
来源:互联网 发布:悟 无人机 知乎 编辑:程序博客网 时间:2024/05/23 07:22
1.题目
http://acm.hdu.edu.cn/showproblem.php?pid=2473
2.分析
并查集删除点的做法:不是真正删除,而是将所有节点全部处理成非根节点,这样在做删除操作的时候,只用换一下根节点即表示删除了根节点。
如果在[0,N]中选择根节点,则不可避免的需要处理两种情况:删除非根节点;删除根节点;程序中如果直接建图添加这两种操作,则会导致TLE,因为数据量太大。
(自己做的时候用的就是直接建图添加考虑两种删除操作的思路,毫无疑问TLE)
参考网上的代码分析思路:将[0,N-1]中的所有点处理成并查集集合中的非根节点,这样在处理删除操作的时候只用换一下其对应的根节点即可,不用考虑删除该点之后会对其所处集合的影响(例如:删除非根节点怎么办?删除根节点怎么办?) 具体的处理过程为:初始化和合并的时候将[0,N-1]中的所有父节点处理成[N,2*N-1]中的节点;当需要删除节点的时候将其父节点修改为[2*N,3*N-1]中的点,保证[0,N-1] 都是集合中的非根节点。
3.复杂度
空间复杂度为O(N),建立一个集合的时间复杂度为O(1),N次合并M次查找的时间复杂度为O(MAlpha(N)),这里Alpha是Ackerman函数的某个反函数,在很大的范围内(人类目前观测到的宇宙范围估算有10的80次方个原子,这小于前面所说的范围)这个函数的值可以看成是不大于4的,所以并查集的操作可以看做是线性的。
4.涉及内容
数据结构:并查集
5.感想
如果碰到大数据题目发现超时,则可靠的做法是尽量不要存在遍历数据的操作,尽量用开辟大数组的方法来记录结果。(自己体会用空间换时间的思想,很深奥啊)
6.代码
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <algorithm>long f2473[1200005],N,M,top;long a2473[100005];void makeset2473(){for(long i=0;i<N;++i)f2473[i]=i+N;for(long i=N;i<1200005;++i)f2473[i]=i;}long find2473(long x){return f2473[x]==x?f2473[x]:f2473[x]=find2473(f2473[x]);}void union2473(long r1,long r2){long a=find2473(r1);long b=find2473(r2);if(a==b) return ;f2473[a]=b;}int main(){freopen("in.txt","r",stdin);long k=0,A,B;char op[5];;while(1)//将scanf写到while循环中不是一个好主意,总会发生不可思议的事情 {scanf("%ld%ld",&N,&M);if(N==0&&M==0) break;top=N+N; makeset2473(); for(int i=0;i<M;++i) { scanf("%s",&op); switch(op[0]) {case 'M':{scanf("%ld%ld",&A,&B);union2473(A,B);}break;case 'S':{scanf("%ld",&A);f2473[A]=top++;}break; } }for(long i=0;i<N;++i)a2473[i]=find2473(i);std::sort(a2473,a2473+N); A=1;for ( long i = 1; i < N; ++ i )if ( a2473[i] != a2473[i-1] ) A ++;printf("Case #%d: %d\n",++k,A);}return 0;}
7.参考文献
http://www.cppblog.com/MiYu/archive/2010/08/26/124771.html 思路一样
http://blog.csdn.net/xingyeyongheng/article/details/8823300 在处理合并和删除的时候就记录剩下的集合数量,其中的删除操作也是通过添加虚拟点实现,和下面的思路相同
http://www.cnblogs.com/fornever/archive/2011/11/08/2240751.html 分析如下
{
将合并的数据(来自集合[0,N-1])看做最终数据数组A,B的索引。数组A用于并查集内部的操作,数组B用于索引查找真正的根节点,其中包含新添加的节点。
这样当删除节点x之后,x节点对应的新的虚拟节点存在数组B中,当后面有处理和x相关的合并操作的时候,可以直接在B中查到新的节点来操作。
这样能够正确处理程序的原因是:每次在执行union操作的时候参数用的都是B数组中的数据(b包含新增加节点的数据),从而保证能正确删除
这样当删除节点x之后,x节点对应的新的虚拟节点存在数组B中,当后面有处理和x相关的合并操作的时候,可以直接在B中查到新的节点来操作。
这样能够正确处理程序的原因是:每次在执行union操作的时候参数用的都是B数组中的数据(b包含新增加节点的数据),从而保证能正确删除
}
- hud 2473 Junk-Mail Filter
- 2473 Junk-Mail Filter
- HDU 2473 Junk-Mail Filter
- hdoj 2473 Junk-Mail Filter
- HDU 2473 Junk-Mail Filter
- HDU 2473 Junk-Mail Filter
- hdu 2473 Junk-Mail Filter
- HDU 2473 Junk-Mail Filter
- hdu 2473 Junk-Mail Filter
- HDU 2473 Junk-Mail Filter
- HDU 2473 Junk-Mail Filter
- HDU-2473 Junk-Mail Filter
- hdoj 2473 Junk-Mail Filter
- HDU 2473 Junk-Mail Filter
- HDU-2473-Junk-Mail Filter
- hdu 2473 Junk-Mail Filter
- HDU 2473 Junk-Mail Filter(删点)
- HDOJ 2473 Junk-Mail Filter(并查集删点)
- 将String 转成 charsequence -java -android 帮助为EditText赋值
- 【法向量】让人无法理解的法向量
- vb.net用API函数getWindowRect()获取窗体位置信息失败解决
- Ubuntu12.10 下搭建基于KVM-QEMU的虚拟机环境(二)
- 容器
- hud 2473 Junk-Mail Filter
- Linux下查看用户登陆后的操作记录
- 深入理解spring注解(1)java注解基础
- 用Redis实现Session功能
- eclipse连接小米2调试程序的问题
- Android 设备编译方法
- 谈23种设计模式
- Visual C++中的ADO编程
- for循环详解