find的递归实现,路径压缩
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include<iostream> #include<cstdio> using namespace std; const int MAXN=10005; int a[MAXN];
int find(int x){ if(x!=a[x])a[x]=find(a[x]); return a[x]; }
inline void unite(int x,int y){ a[find(x)]=find(y); }
int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) a[i]=i; int x,y,z; for(int i=1;i<=m;i++){ scanf("%d%d%d",&z,&x,&y); if(z==1)unite(x,y); else if(find(x)==find(y))printf("Y\n"); else printf("N\n"); } return 0; }
|
另外,find操作的非递归写法,不过效率差别不大
这里要注意一点,find函数里的t数组一定不要初始化。因为不初始化是常数级,初始化是n级的,相差很大。
1 2 3 4 5 6 7 8 9 10
| inline int find(int x){ int k,i,t[MAXN]; for(k=1;a[x]!=x;k++){ t[k]=x; x=a[x]; } for(i=1;i<=k-1;i++) a[t[i]]=x; return x; }
|
又尝试了C++面向对象实现(
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| #include<iostream> #include<cstdio> #include<malloc.h> using namespace std;
struct node{ int father; int data; };
class union_find{ public: void init(int max){ set=(struct node *)malloc(sizeof(struct node)*max); t=(int *)malloc(sizeof(int)*max); for(int i=0;i<max;i++){ set[i].father=i; set[i].data=i; } } int find(int x){ int k=0,i; while(set[x].father!=x){ k++; t[k]=x; x=set[x].father; } for(i=1;i<=k-1;i++) set[t[i]].father=x; return x; } void unite(int x,int y){ set[find(x)].father=find(y); } bool same_set(int x,int y){ return find(x)==find(y); } void dispose(){ free(set); free(t); } private: int *t; struct node *set; };
int main(){ int n,m; scanf("%d%d",&n,&m); int zi,xi,yi; int i; union_find a; a.init(10005);
for(i=1;i<=m;i++){ scanf("%d%d%d",&zi,&xi,&yi); if(zi==1){ a.unite(xi,yi); } else if(zi==2){ if(a.same_set(xi,yi))printf("Y\n"); else printf("N\n"); } } return 0; }
|