题目链接: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.
}