nyoj1022合纵连横(带分离操作的并查集)

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=1022

题目解析:带分离操作的并查集,当删除结点时,重新引入一个新的结点即新的结点代替原来的结点,即将map[]数组的值被新的结点代替,father[]数组的值是自己本省,即是自己的根,当再对先前结点操作时,就直接操作新的结点。需要注意的一点是下面代码的vis[]数组。

代码如下;

01. #include<cstdio>
02. #include<cstring>
03. #include<algorithm>
04. using namespace std;
05.  
06. const int N=1e5+1e5+9;
07. int father[N];
08. int map[N];
09. bool vis[N];
10. int p,q;
11. int top;
12. void init(int n)
13. {
14. for(int i=0;i<n;i++)
15. father[i]=i;
16. for(int i=0;i<n;i++)
17. map[i]=i;
18. }
19. int find(int n)
20. {
21. if(n==father[n])
22. return n;
23. else
24. return find(father[n]);
25. }
26. void merge(int m,int n)
27. {
28. int a=find(m);
29. int b=find(n);
30. if(a>b)
31. father[a]=b;
32. else
33. father[b]=a;
34. }
35. void apart(int n)
36. {
37. int t=top++;
38. map[n]=t;
39. father[t]=t;
40. }
41.  
42. int main()
43. {
44. int icase=1;
45. while(scanf("%d%d",&p,&q)!=EOF)
46. {
47. top=p;
48. init(p);
49. char str[3];
50. int u,v;
51. while(q--)
52. {
53. scanf("%s",str);
54. if(str[0]=='U')
55. {
56. scanf("%d%d",&u,&v);
57. merge(map[u],map[v]);
58. }
59. else
60. {
61. scanf("%d",&u);
62. apart(u);
63. }
64. }
65. memset(vis,false,sizeof(vis));
66. for(int i=0;i<p;i++)
67. vis[find(map[i])]=true;
68. int ans=0;
69. for(int i=0;i<top;i++)
70. {
71. if(vis[i])
72. ans++;
73. }
74. printf("Case #%d: %d\n",icase++,ans);
75. }
76. return 0;
77. }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值