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

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

题意——

给定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. Android ActionBar下拉选项

    package com.example.actionBarTest.actionBarList; import android.app.ActionBar; import android.app.Ac ...

  2. TopCoder 649 div1 & div2

    最近一场TC,做得是在是烂,不过最后challenge阶段用一个随机数据cha了一个明显错误的代码,最后免于暴跌rating,还涨了一点.TC题目质量还是很高的,非常锻炼思维,拓展做题的视野,老老实实 ...

  3. [转]Java数组初始化详解

    一维数组1)   int[] a;   //声明,没有初始化 2)   int[] a=new int[5];   //初始化为默认值,int型为0 3)   int[] a={1,2,3,4,5}; ...

  4. jquery通过ajax-json访问java后台传递参数,通过request.getParameter获取不到参数的说明

    http://m.blog.csdn.net/blog/eyebrother/36007145 所以当后台通过request.getParameter("name");对参数值的作 ...

  5. GuessNum

    import java.util.Scanner;import java.util.Random;/***猜数字,使用随机一个0-100的数字,然后用户猜,猜中了就提示猜中了,*否则提示猜大了还是猜小 ...

  6. Ossec常用命令

    启动并查看httpd服务 systemctl start httpd systemctl status httpd.service 启动并查看mysql服务 systemctl start maria ...

  7. UVa 11922 - Permutation Transformer 伸展树

    第一棵伸展树,各种调试模板……TVT 对于 1 n 这种查询我处理的不太好,之前序列前后没有添加冗余节点,一直Runtime Error. 后来加上冗余节点之后又出了别的状况,因为多了 0 和 n+1 ...

  8. js问题总结

    .removeClass(" ") 移除一个css样式 $("#popUpBox i").removeClass("channel_icon" ...

  9. Android应用开发学习笔记之Intent

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Intent是什么呢?来看Android官网上的定义: An intent is an abstractdescri ...

  10. 25-语言入门-25-n-1位数

    题目地址: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=96    描述已知w是一个大于10但不大于1000000的无符号整数,若w是n(n ...