1. 程式人生 > >2018.09.12 hdu2473Junk-Mail Filter(並查集)

2018.09.12 hdu2473Junk-Mail Filter(並查集)

傳送門 一開始開題還以為是平衡樹。 仔細想了一想並查集就可以了。 合併操作沒什麼好說的。 刪除操作:對於每個點記錄一個pos值表示原來的點i現在的下標是什麼。 每次刪除點i是就新建一個點cnt,然後令pos[i]=cnt就行了。 程式碼;

#include<bits/stdc++.h>
#define N 1200005
using namespace std;
inline int read(){
    int ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3
)+(ans<<1)+(ch^48),ch=getchar(); return ans; } int n,m,fa[N],pos[N],cnt=0,T=0; bool vis[N]; inline int find(int x){return x==fa[x]?fa[x]:fa[x]=find(fa[x]);} int main(){ while(n=read(),m=read(),n||m){ ++T; cnt=n; for(int i=1;i<=n+m;++i)fa[i]=i,pos[i]=i,vis[i]=false; while
(m--){ char s[2]; scanf("%s",s); if(s[0]=='M'){ int x=read()+1,y=read()+1,fx=find(pos[x]),fy=find(pos[y]); if(fx!=fy)fa[fx]=fy; } else{ int x=read()+1; pos[x]=++cnt; } } int
ans=0; for(int i=1;i<=n;++i)if(!vis[find(pos[i])])vis[find(pos[i])]=1,++ans; printf("Case #%d: %d\n",T,ans); } return 0; }