传送门

题意:

每次合并两份邮件,或者将某一份邮件独立出来,问最后有多少个邮件集合。

分析:

考虑初始化每个节点的祖先为一个虚父节点(i + n),虚父节点指向它自己。这样可以进行正常的合并操作。

而在删除时,将该节点的祖先置为一个更大的数(++anc_cnt),并让该anc_cnt指向它自己,这样不会影响与自身节点相连的所有关系。最后统计有多少个不同的祖先即可。

code

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5, M = 1e6 + 5;
int n, anc[N * 12], x, y, vt, k, m, anc_cnt, ans, vst[N * 12];
char opt[5];
inline int getAnc(int x){return x == anc[x] ? x : (anc[x] = getAnc(anc[x]));}
inline void merge(int x, int y){
int fx = getAnc(x), fy = getAnc(y);
if(fx != fy) anc[fx] = fy;
}
inline void del(int x){anc[x] = ++anc_cnt; anc[anc_cnt] = anc_cnt;}
int main(){
freopen("h.in", "r", stdin);
while(scanf("%d%d", &n, &m) && (n + m)){
for(int i = 1; i <= n; i++) anc[i] = i + n, anc[i + n] = i + n;
anc_cnt = n * 2, ans = 0; vt++;
for(int i = 1; i <= m; i++){
scanf("%s", opt + 1);
if(opt[1] == 'M'){
scanf("%d%d", &x, &y);
x++, y++;
merge(x, y);
}
else{
scanf("%d", &x);
x++;
del(x);
}
}
for(int i = 1; i <= n; i++){
int f = getAnc(i);
if(vst[f] != vt) ans++;
vst[f] = vt;
}
printf("Case #%d: %d\n", ++k, ans);
}
return 0;
}

最新文章

  1. Fiddler学习笔记
  2. oracle/MySQL 中的decode的使用
  3. SQL Server对Xml字段的操作
  4. iOS 自定义对象转NSDictionary
  5. Lua简易入门教程
  6. Navicat MySQL连接Linux下MySQL的问题解决方案
  7. js之数组常见的方法
  8. 用来用去还是觉得SDCMS好用
  9. HDU 3836 Equivalent SetsTarjan+缩点)
  10. offset获取位置
  11. activity生命周期分析(两个activity之间跳转的生命周期执行顺序)
  12. 标准模型和IE模型的区别:
  13. STL list 的insert()和erase()
  14. 【代码笔记】Web-JavaScript-JavaScript调试
  15. 修改spring源码重写classloader实现项目加密
  16. C++中extern(转)
  17. windows Git Bash 无法运行python解决方法
  18. Windows如何安装Android SDK
  19. drupal 内容类型
  20. 最简单的VS-Qt-CMake项目框架

热门文章

  1. TextView-属性大全(设置超链接颜色)
  2. HTML5 API 是什么
  3. 理解String的compareTo()方法返回值
  4. CSS笔记 - fgm练习 2-7 - 简易选项卡
  5. 【Codeforces Round #301 (Div. 2) B】 School Marks
  6. poj1679 The Unique MST(判定次小生成树)
  7. GMTC2019会后:做一场冷门的技术专场是什么体验
  8. js面向对象的选项卡
  9. spark提交应用的方法(spark-submit)
  10. int to str