感觉有些难的题,刚开始就想到了设立虚节点,但是实现总是出错,因为每次设立了虚节点之后,无法将原节点和虚节点分开,导致虚节点根本无意义。

以上纯属废话,可以忽略……

题意——

给定n个点(0, 1, 2, ..., n-1),可进行两种操作:1. 将两个点合并到一个集合中; 2. 将一个点从原有集合中取出。问最后点有几个集合。

很明显的并查集,包含合并,删除操作。

但是,删除某节点的时候,需要保证这个集合中,除了被删除节点的其它节点不变,这点有些难以处理。

我们知道,并查集其实是一棵棵树,我们将树中某节点删除,还要保证树的结构不变,可以采用一种方法,那就是“虚节点”,也就是说,我们并不删除那个节点,却将需要删除的节点中保存的数据转移到一个新的节点中,这个节点独立于这棵树之外。这样一来,我们查询那个节点的时候,会查询到新的节点,而原本的节点的作用仅仅是保持树的结构。

因此,我们需要两个数组,一个数组是fm[N+M],一个数组是fle[N],其中fle[]数组的fle[i]表示第i个节点的值,而fm[]数组中,fm[fle[i]]用来保存第i个节点的前驱,即fle[i]的父节点。

重点就在于这个fle[],每次删除节点i时,我们不改变fm[fle[i]],这样树的结构就不会变,而我们赋予fle[i]一个从未使用过的新值,就使实际上的i节点变化了。

这样每次删除i节点,都只需要赋予fle[i]一个从未用过的新值,类似于给i节点换一个新马甲,就可以解决问题。

我们可以从值为n开始,给节点赋的值依次为n++,这样,因为最多M次操作,那么最多换M个马甲,因此,fm的大小为M+N。

上代码——

 #include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std; const int N = ;
const int M = ; bool vis[N+M];
int fm[N+M], fle[N];
int n, m, a, b, pt, ans, tm;
char s[]; void init()
{
for(int i = ; i < n; i++)
{
fm[i] = i;
fle[i] = i;
}
memset(vis, , sizeof(vis));
pt = n;
ans = ;
} int mfind(int a)
{
int fa = a; while(fa != fm[fa]) fa = fm[fa];
while(a != fm[a])
{
int mid = fm[a];
fm[a] = fa;
a = mid;
}
return fa;
} void mmerge()
{
int fa = mfind(fm[fle[a]]);
int fb = mfind(fm[fle[b]]);
if(fa != fb) fm[fa] = fb;
} void dmerge()
{
fle[a] = pt; //换马甲
fm[pt] = pt; //给这个新值初始化父节点
pt++; //为新马甲做准备
} void work()
{
while(m--)
{
scanf("%s", s);
if(s[] == 'M')
{
scanf("%d%d", &a, &b);
mmerge();
}
else if(s[] == 'S')
{
scanf("%d", &a);
dmerge();
}
} for(int i = ; i < n; i++)
{
int ance = mfind(fle[i]);
if(!vis[ance])
{
ans++;
vis[ance] = ;
}
}
printf("Case #%d: %d\n", tm++, ans);
} int main()
{
//freopen("test.in", "r", stdin);
tm = ;
while(~scanf("%d%d", &n, &m) && (n+m))
{
init();
work();
}
}

ps: 这几天状态一直不好,但是今天突然看见一句话,感由心生,终于耐下心来弄明白了这道题——心若没有栖息的地方,在哪里都是流浪

继续加油吧……

hdu 2473 Junk-Mail Filter(并查集_虚节点)2008 Asia Regional Hangzhou的更多相关文章

  1. HDU 2492 Ping pong(数学+树状数组)(2008 Asia Regional Beijing)

    Description N(3<=N<=20000) ping pong players live along a west-east street(consider the street ...

  2. HDU 2491 Priest John's Busiest Day(贪心)(2008 Asia Regional Beijing)

    Description John is the only priest in his town. October 26th is the John's busiest day in a year be ...

  3. hdu 2473 Junk-Mail Filter (并查集之点的删除)

    Junk-Mail Filter Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  4. 《程序员代码面试指南》第三章 二叉树问题 Tarjan算法与并查集解决二叉树节点间最近公共祖先的批量查询问题

    题目待续.... Tarjan算法与并查集解决二叉树节点间最近公共祖先的批量查询问题 java代码

  5. HDU 2473 Junk-Mail Filter 并查集,虚拟删除操作

    http://acm.hdu.edu.cn/showproblem.php?pid=2473 给定两种操作 第一种是合并X Y 第二种是把X分离出来,就是从原来的集合中分离出来,其它的关系不变. 关键 ...

  6. HDU 2473 Junk-Mail Filter(并查集的删除操作)

    题目地址:pid=2473">HDU 2473 这题曾经碰到过,没做出来. .如今又做了做,还是没做出来. ... 这题涉及到并查集的删除操作.想到了设一个虚节点,可是我把虚节点设为了 ...

  7. 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~ ...

  8. HDU 2473 Junk-Mail Filter(并查集+删点,设立虚父节点/找个代理)

    题意:有N封邮件, 然后又两种操作,如果是M X Y , 表示X和Y是相同的邮件.如果是S X,那么表示对X的判断是错误的,X是不属于X当前所在的那个集合,要把X分离出来,让X变成单独的一个.最后问集 ...

  9. (step5.1.2)hdu 2473(Junk-Mail Filter——并查集)

    题目大意:输入两个整数n,m(n表示点的个数,m表示操作数).在接下来的m行中,对点的操作有两种 1)M a b . 表示将a.b并到一个集合中 2)S a .表示将a从原来的集合中去除,而成为一个单 ...

随机推荐

  1. StringBuffer用法

    public class StringBufferTest { public static void main(String[] args) { StringBuffer sb=new StringB ...

  2. jQuery动画效果实现

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  3. 独立IP与共享IP的区别

    做网站选择独立IP还是共享IP,相信很多站长都在此纠结过,自己不使用服务器的时候从来没有关心过独立IP和共享IP的究竟有什么具体的差别.但当自己真正用到的时候,才发现:同样都是 IP,差别不是一般的大 ...

  4. lintcode 中等题:majority number III主元素III

    题目 主元素 III 给定一个整型数组,找到主元素,它在数组中的出现次数严格大于数组元素个数的1/k. 样例 ,返回 3 注意 数组中只有唯一的主元素 挑战 要求时间复杂度为O(n),空间复杂度为O( ...

  5. lintcode: 爬楼梯

    题目: 爬楼梯 假设你正在爬楼梯,需要n步你才能到达顶部.但每次你只能爬一步或者两步,你能有多少种不同的方法爬到楼顶部? 样例 比如n=3,中不同的方法 返回 3 解题: 动态规划题目,同时还是有顺序 ...

  6. POJ1118 Lining Up

    快弄死我了 最后的原因是abs和fabs的区别... 说点收获:1.cmp函数返回的是int,所以不要直接返回double相减的结果2.define inf 1e9和eps 1e-93.在整数相除得到 ...

  7. Web 技术人员需知的Web 缓存知识

    最近的译文距今已有4年之久,原文有一定的更新.今天踩着前辈们的肩膀,再次把这篇文章翻译整理下.一来让自己对web缓存的理解更深刻些,二来让大家注意力稍稍转移下,不要整天HTML5, 面试题啊叨啊叨的~ ...

  8. 关于NGUI制作图集在低内存设备上的注意事项

    正在写一个游戏.由于2D且比较简单.打算用NGUI全权搞定,对,游戏内容也用NGUI. 想的很好,做的很爽.PC上跑起来happy. 天杀的诺基亚出了个手机叫lumia520,可用内存512M.单个程 ...

  9. Java学习笔记之:Java StringBuffer类

    一.引言 当对字符串进行修改的时候,需要使用StringBuffer类. 和String类不同的是,StringBuffer和StringBuilder类的对象能够被多次的修改,并且不产生新的未用对象 ...

  10. TCL语言笔记:TCL中的数组

    一.介绍 Tcl 中的数组和其他高级语言的数组有些不同:Tcl 数组元素的索引,或称键值,可以是任意的字符串,而且其本身没有所谓多维数组的概念.数组的存取速度要比列表有优势,数组在内部使用散列表来存储 ...