这道题一开始本来想用直接改变p[i],使得p[i]=i,发现虽然路径压缩过了,但是实际上i下面所连接的点并没有压缩到i原本的根上,如图
而实际上应该是
所以就需要让1这个点依旧存在于这棵树里边,另外用一个变量来表示1这个点已经被删除掉
实际上右边的点一开始也是由sham构成的树,因为初始化的sham数组都为本身,只有当删除过某个点(图中为删除1点),那么sham[1]指向了原来不存在一个点,而右边的树里1还是没有改变,所以2的根依旧可以找到0,因为set的过程中都是set sham这一数组,所以再就不会寻找到sham[1]在右边的这棵树里。
- #include<stdio.h>
- #include<string.h>
- int sham[100010],p[1100010],flag[1100010],id;
- int find(int n)
- {
- if(p[n]!=n)
- {
- p[n]=find(p[n]);
- }
- return p[n];
- }
- void set(int x,int y)
- {
- p[find(x)]=find(y);
- }
- void del(int x)
- {
- sham[x]=id;
- p[sham[x]]=id;
- id++;
- }
- int main()
- {
- int m,n;
- int cas=1;
- while(scanf("%d%d",&n,&m)!=EOF)
- {
- int cnt;
- if(n==0&&m==0)
- {
- break;
- }
- for(int i=0;i<n;i++)
- {
- sham[i]=p[i]=i;
- }
- char c[3];
- id=n;
- for(int i=0;i<m;i++)
- {
- scanf("%s",c);
- if(c[0]=='M')
- {
- int x,y;
- scanf("%d%d",&x,&y);
- set(sham[x],sham[y]);
- }
- else
- {
- int x;
- scanf("%d",&x);
- del(x);
- }
- }
- cnt=0;
- memset(flag,0,sizeof(flag));
- for(int i=0;i<n;i++)
- {
- int x=find(sham[i]);
- if(flag[x]==0)
- {
- cnt++;
- flag[x]=1;
- }
- }
- printf("Case #%d: %d\n",cas++,cnt);
- }
- }