(step5.1.2)hdu 2473(Junk-Mail Filter——并查集)
题目大意:输入两个整数n,m(n表示点的个数,m表示操作数)。在接下来的m行中,对点的操作有两种
1)M a b 。 表示将a、b并到一个集合中
2)S a .表示将a从原来的集合中去除,而成为一个单独的集合
解题思路:并查集
1)
解题思路:并查集,M代表合并,S代表删除,下面讲一下删除操作
大家都知道合并操作就是找到找到两个节点的父亲,修改父亲,如果删除就是将该点的父亲重新设置成自己,这样行不行呢?
这是不行的,比如1,2,3的父亲都是1,现在删除1,1的父亲还是1,2,3也是1,集合还是1个,正确的应该是2个。
那删除节点的父亲不设成自己给新申请一个节点当做父亲,比如1,2,3的父亲都是1,在一个集合,现在删除1,申请了4当做1的父亲,2,3父亲都是1,然后Find(2)找2的父亲
2的父亲是1,但是1的父亲是4,所以给2的父亲更新成了4,3同理,所以还不行。
正确的方法是每一个点都设立一个虚拟父亲比如1,2,3的父亲分别是4,5,6,现在合并1,2,3都在一个集合,那他们的父亲都是4,现在删除1,那就给1重新申请一个节点7
现在2,3的父亲是4,1的父亲是7,删除成功。
2)定义数组 int[] father
int[] rank
father[i]=i,则i表示本集合且i是集合对应的树的根
father[i]=j,则表示j是i的父节点
rank[i]代表集合i的秩(比如子孙的多少或树的高度等),用于合并集合,秩小的合并到秩大的。
3)
开始让我混淆的一个地方是,假设如下情况
M 0 2
M 1 2
S 2
那么按照并查集来做, 0指向2, 1指向2,即
0 -->2
1 -->2 ,
那么删除2之后,我以为题目意思是所有与2有关系的都要删除, 那么这两个关系都要去掉, 又变成独立的3个了。
但是我这种理解是错的。 合并起来后就是一个集合{0,1,2}, 如果把2删除掉之后, {0,1}还是集合。
理解题意之后, 我们知道用并查集来构造集合是很容易的,但是要把集合中的一个删掉,却很不容易。 通过这题,我学习到了所谓的设立需父节点的方法。
关键的过程是假设要删除x点, 那么不是真的删除x点, 而是通过一个映射(这里用数组majia[N]),把x变成一个新的点即majia[x] = newNode.那么, 原来的那些集合还是不变,只是少了个x点。
-----------------------------------------------------------------------------------------------------
以下代码是根据解题思路1)写出来的。
代码如下:
/*
* 2473_4.cpp
*
* Created on: 2013年8月23日
* Author: Administrator
*/ #include <iostream> using namespace std; int father[1100000];
bool flag[1000050];
int id; int find(int x){
int r,i,j; r = x;
while( r!= father[r]){
r = father[r];
} i = x;
while(i!=r){
j = father[i];
father[i] = r;
i = j;
} return r;
} /**find(int a) 也可以写成以下形式:
int find(int a){
if(a != father[a]){
father[a] = find(father[a]);
} return father[a];
}
*/
void join(int x , int y){
int fx = find(x);
int fy = find(y); if(fx != fy){
father[fx] = fy;
}
} void make_set(int n , int m){
int i;
for(i = 0 ; i < n ; ++i){
father[i] = i + n;
} for(i = n ; i <= n + n + m ; ++i){
father[i] = i;
}
} void delete_set(int x){
father[x] = id++;
} int main(){
int n,m,count = 1;
while(scanf("%d%d",&n,&m)!=EOF,n||m){
int i;
id = n + n;
make_set(n,m);//****千万别漏了
for( i = 0 ; i < m ; ++i){
int a,b;
char c[5];
scanf("%s",c);
if(c[0] == 'M'){
scanf("%d%d",&a,&b);
join(a,b);
}else if(c[0] == 'S'){
scanf("%d",&a);
delete_set(a);
}
} memset(flag,0,sizeof(flag));
int ans = 0;
for( i = 0 ; i < n ; ++i){
int x = find(i);
if(!flag[x]){
ans++;
flag[x] = true;
}
} printf("Case #%d: %d\n",count++,ans); }
}
(step5.1.2)hdu 2473(Junk-Mail Filter——并查集)的更多相关文章
- (step5.1.6)hdu 1272(小希的迷宫——并查集)
题目大意:输入一系列的点,判断这些点组成的图符不符合小希的思路(无环.连通) 解题思路: 1)如果两个节点的根节点相同,那么在这两个节点之间添加1条边以后,这个图肯定有环路. 2)孤立节点:被使用过& ...
- hdu 2473 Junk-Mail Filter (并查集之点的删除)
Junk-Mail Filter Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- HDU 2473 Junk-Mail Filter 并查集,虚拟删除操作
http://acm.hdu.edu.cn/showproblem.php?pid=2473 给定两种操作 第一种是合并X Y 第二种是把X分离出来,就是从原来的集合中分离出来,其它的关系不变. 关键 ...
- HDU 2473 Junk-Mail Filter(并查集的删除操作)
题目地址:pid=2473">HDU 2473 这题曾经碰到过,没做出来. .如今又做了做,还是没做出来. ... 这题涉及到并查集的删除操作.想到了设一个虚节点,可是我把虚节点设为了 ...
- HDU 2473 Junk-Mail Filter 并查集删除(FZU 2155盟国)
http://acm.hdu.edu.cn/showproblem.php?pid=2473 http://acm.fzu.edu.cn/problem.php?pid=2155 题目大意: 编号0~ ...
- hdu2473 Junk-Mail Filter 并查集+删除节点+路径压缩
Description Recognizing junk mails is a tough task. The method used here consists of two steps: 1) ...
- HDU HDU1558 Segment set(并查集+判断线段相交)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1558 解题报告:首先如果两条线段有交点的话,这两条线段在一个集合内,如果a跟b在一个集合内,b跟c在一 ...
- hdu 1257 小希的迷宫 并查集
小希的迷宫 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1272 D ...
- hdu 3635 Dragon Balls(并查集应用)
Problem Description Five hundred years later, the number of dragon balls will increase unexpectedly, ...
- <hdu - 1272> 小希的迷宫 并查集问题 (注意特殊情况)
本题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1272 Problem Description: 上次Gardon的迷宫城堡小希玩了很久(见Probl ...
随机推荐
- Monkeyrunner入门示例
准备工作1.安装Android SDK2.熟悉MonkeyRunner的API(http://article.yeeyan.org/view/37503/164523)3.一部Android手机或模拟 ...
- Meth | 安装Linux Mint 18以后grub2 win10启动引导项丢失??!!
进入mint,打开终端输入:sudo update-grub2
- C++笔试题库-------Coding整理
1. 反转字符串 char* strrev1(const char* str) { int len = strlen(str); ]; char *p = temp + len; *p = '\0'; ...
- iOS 启动连续闪退保护方案
引言 “如果某个实体表现出以下任何一种特性,它就具备自主性:自我修复.自我保护.自我维护.对目标的自我控制.自我改进.” —— 凯文·凯利 iOS App 有时可能遇到启动必 crash 的绝境:每次 ...
- Day7 - Python基础7 面向对象编程进阶
Python之路,Day7 - 面向对象编程进阶 本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个 ...
- 176. [USACO Feb07] 奶牛聚会
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #defin ...
- 如何在ASP.NET端获取屏幕宽度
using System.Windows.Forms; 首先引用上面的命名空间. 然后在代码中获取屏幕信息.如下代码: System.Windows.Forms.Screen screen = Sys ...
- Notification封装(没做从网络下载)
1.Notification作为消息通知,这里简单封装了使用 建立一个bean package com.jcut.view; /** * Author:JsonLu * DateTime:2016/2 ...
- Web弹框类
using System; using System.Text; namespace Core { /// <summary> /// MessageBox 的摘要说明. /// < ...
- Android onConfigurationChanged(Configuration cfg) 无法触发问题
1.android:configChanges="orientation|keyboardHidden"的使用 当在activity加上android:configChange ...