题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2473

题目大意:

n个点,m个操作,操作时,输入M a b,表示a, b在一个集合里, 输入S a 表示将a从集合里删除掉。求最后有多少个不同的集合。

解题思路:

需要删除结点,但是并非是删除与该节点为父亲节点的子树,而仅仅是该点。所以需要用到虚父节点。

所以再开一个数组,更新节点时直接改变当前节点的父节点,使其等于大于n的父节点,这样就把其节点删除了。

代码如下:

 #include<iostream>
#include<string.h>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int MAXN = 1e6 + ; int n, m, temp, k;
char op;
int p[MAXN], pre[MAXN], flag[MAXN]; int find(int x)
{
if(pre[x] == x)
return x;
else
{
int root = find(pre[x]);
pre[x] = root;
return pre[x];
}
} int main()
{
cin.sync_with_stdio(false);
k = ;
while(cin >> n >> m)
{
if(n == && m == )
break;
temp = n, mem(flag, );
for(int i = ; i < n; i ++)
{
pre[i] = i;
p[i] = i; //虚设
}
for(int i = ; i <= m; i++)
{
cin >> op;
if(op == 'M')
{
int a, b;
cin >> a >> b;
int x = find(p[a]), y = find(p[b]);
if(x != y)
pre[y] = x;
}
else
{
int a;
cin >> a;
p[a] = temp;
pre[temp] = temp;
temp ++;
}
}
int ans = ;
for(int i = ; i < n; i ++)
{
int x = find(p[i]);
if(!flag[x])
{
ans ++;
flag[x] = ;
}
}
cout << "Case #" << k ++ << ": " << ans << endl;
}
return ;
}

同样有一道一样题,更加直观。

乱世天下,诸侯割据。每个诸侯王都有一片自己的领土。但是不是所有的诸侯王都是安分守己的,实力强大的诸侯国会设法吞并那些实力弱的,让自己的领土 面积不断扩大。而实力弱的诸侯王为了不让自己的领土被吞并,他会联合一些其他同样弱小的诸侯国,组成联盟(联盟不止一个),来共同抵抗那些强大的诸侯国。 强大的诸侯国为了瓦解这些联盟,派出了最优秀的间谍来离间他们,使一些诸侯国退出联盟。最开始,每个诸侯国是一个联盟。

有两种操作

1、U x y 表示x和y在同一个联盟。(0≤x,y<n)

2、D x   表示x退出联盟。 仅仅是x退出联盟,对于其他的诸侯国没有影响。因此是删除单个点而不是子树。

输入
多组测试数据
第一行两个数,n和m(1 ≤ n≤ 10^5, 1 ≤ m ≤10^5),分别表示诸侯国的个数和操作次数。
接下来有m行操作
输出
输出联盟的个数
样例输入
5 7
U 0 1
U 1 2
U 0 3
D 0
U 1 4
D 2
U 0 2
10 1
U 0 9 
样例输出
Case #1: 2
Case #2: 9
 #include<iostream>
#include<string.h>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int MAXN = 1e5 + ; int n, m, temp, k;
char op;
int p[MAXN], pre[ * MAXN], flag[ * MAXN]; int find(int x)
{
if(pre[x] == x)
return x;
else
{
int root = find(pre[x]);
pre[x] = root;
return pre[x];
}
} int main()
{
cin.sync_with_stdio(false);
k = ;
while(cin >> n >> m)
{
temp = n, mem(flag, );
for(int i = ; i < n; i ++)
{
pre[i] = i;
p[i] = i; //虚设
}
for(int i = ; i <= m; i++)
{
cin >> op;
if(op == 'U')
{
int a, b;
cin >> a >> b;
int x = find(p[a]), y = find(p[b]);
if(x != y)
pre[y] = x;
}
else
{
int a;
cin >> a;
p[a] = temp;
pre[temp] = temp;
temp ++;
}
}
int ans = ;
for(int i = ; i < n; i ++)
{
int x = find(p[i]);
if(!flag[x])
{
ans ++;
flag[x] = ;
}
}
cout << "Case #" << k ++ << ": " << ans << endl;
}
return ;
}

Junk-Mail Filter 【并查集虚父节点】的更多相关文章

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

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

  2. HDU2473 Junk-Mail Filter - 并查集删除操作(虚父节点)

    传送门 题意: 每次合并两份邮件,或者将某一份邮件独立出来,问最后有多少个邮件集合. 分析: 考虑初始化每个节点的祖先为一个虚父节点(i + n),虚父节点指向它自己.这样可以进行正常的合并操作. 而 ...

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

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

  4. hdu2473 Junk-Mail Filter 并查集+删除节点+路径压缩

    Description Recognizing junk mails is a tough task. The method used here consists of two steps:  1) ...

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

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

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

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

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

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

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

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

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

随机推荐

  1. 1、python--第一天练习题

    #1.使用while循环输入 1 2 3 4 5 6 8 9 10 k = 0 while k < 10: k += 1 if k == 7: continue print(k) #2.求1-1 ...

  2. AtomicInteger如何保证线程安全以及乐观锁/悲观锁的概念

    众所周知,JDK提供了AtomicInteger保证对数字的操作是线程安全的,线程安全我首先想到了synchronized和Lock,但是这种方式又有一个名字,叫做互斥锁,一次只能有一个持有锁的线程进 ...

  3. 8月清北学堂培训 Day3

    今天是赵和旭老师的讲授~ 状态压缩 dp 状态压缩是设计 dp 状态的一种方式. 当普通的 dp 状态维数很多(或者说维数与输入数据有关),但每一维总量很少时,可以将多维状态压缩为一维来记录. 这种题 ...

  4. 7月清北学堂培训 Day 3

    今天是丁明朔老师的讲授~ 数据结构 绪论 下面是天天见的: 栈,队列: 堆: 并查集: 树状数组: 线段树: 平衡树: 下面是不常见的: 主席树: 树链剖分: 树套树: 下面是清北学堂课程表里的: S ...

  5. 1558:聚会 ybt

    1558:聚会 ybt 题解(看似很难,其实要是摸清了实质这就是个大水题) 上题目 1558:聚会 时间限制: 1000 ms         内存限制: 524288 KB提交数: 82     通 ...

  6. 2Dot grammar

    http://www.cnblogs.com/mjios/archive/2013/04/08/3006577.html . #import <Foundation/Foundation.h&g ...

  7. java.security.InvalidKeyException: Illegal key size or default parameters

    今天在使用idea打包maven项目时,出现这个错误:java.security.InvalidKeyException: Illegal key size or default parameters ...

  8. 六、grep与正则表达式 (文本过滤)

    一.正则表达式 正则表达式:Regual Expression, REGEXP.由一类特殊字符及文本字符所编写的模式,其中有些字符不表示其字面意义,而是用于表示控制或通配的功能:基本正则表达式:BRE ...

  9. jinja2-模版简介

    一 简介 在Flask中,调用render_template来对模版进行渲染,使用render_template,只需要导入这个API就可以,from flask import render_temp ...

  10. Web Services之基本认识

    参考:http://www.w3school.com.cn/webservices 1.什么是Web Services Web Services 可使您的应用程序成为 Web 应用程序.Web Ser ...