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

来源:互联网 发布:超值的网络推广多少钱 编辑:程序博客网 时间:2024/06/06 00:28

题目链接: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
原创粉丝点击