题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2473
思路:就是每次删除节点的时候并不是把节点删除,而是单独成一个集合。。。
以前不知道为什么每次做并查集的时候,总是TLE。。。今天终于是找到原因了,然后找出来以前TLE的代码,然后一个就过了。。。
不多说了,具体见代码:
View Code
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int MAXN=1000000+10; 6 int n,m; 7 int parent[MAXN],id[MAXN],Rank[MAXN]; 8 9 void Initiate(){ 10 for(int i=0;i<n;i++){ 11 //parent[i]=i; 12 parent[i]=-1; 13 Rank[i]=1,id[i]=i; 14 } 15 } 16 17 int Find(int x){ 18 /* 19 if(x!=parent[x]){ 20 parent[x]=Find(parent[x]); 21 } 22 return parent[x]; 23 */ 24 int s; 25 for(s=x;parent[s]>=0;s=parent[s]); 26 while(s!=x){ 27 int tmp=parent[x]; 28 parent[x]=s; 29 x=tmp; 30 } 31 return s; 32 } 33 34 35 void Union(int R1,int R2){ 36 int r1=Find(R1); 37 int r2=Find(R2); 38 if(r1==r2)return ;//必须加啊!!!,不然TLE 39 if(parent[r1]>parent[r2]){ 40 parent[r1]+=parent[r2]; 41 parent[r2]=r1; 42 Rank[r1]+=Rank[r2]; 43 Rank[r2]=0; 44 }else { 45 parent[r2]+=parent[r1]; 46 parent[r1]=r2; 47 Rank[r2]+=Rank[r1]; 48 Rank[r1]=0; 49 } 50 } 51 52 int main(){ 53 int _case=1; 54 while(~scanf("%d%d",&n,&m)&&(n+m)){ 55 Initiate(); 56 int num=n; 57 for(int i=1;i<=m;i++){ 58 char str[11]; 59 scanf("%s",str); 60 if(str[0]=='M'){ 61 int u,v; 62 scanf("%d%d",&u,&v); 63 Union(id[u],id[v]); 64 }else if(str[0]=='S'){ 65 int x; 66 scanf("%d",&x); 67 int y=Find(id[x]); 68 Rank[y]--;//元集合中的元素减少 69 id[x]=num;//映射被删除的节点 70 // id[num]=num; 71 parent[num]=-1;//独立成一个集合 72 Rank[num]=1; 73 num++; 74 } 75 } 76 int ans=0; 77 for(int i=0;i<num;i++){ 78 if(Rank[i]>0)ans++; 79 } 80 printf("Case #%d: %d\n",_case++,ans); 81 } 82 return 0; 83 }