并查集,如果只是朴素的路径压缩,那么也就是一句话的事情。
但是,一般都没有这种仁慈的裸题(假的,多了去了)
1988:带权并查集,贼鸡儿像Luogu的那道杨威利的并查集(好像是叫银河英雄传说)
开两个数组,down[x]表示标号为x的箱子下面有多少个箱子,len[x]表示以x点为根(即被压在最底部的箱子)的箱子总个数是多少。
因此我们在合并时,要把fx的父节点更新为fy,同时还要更新down[fx]和len[fy]。当然,最容易忽略的是把len[fx]清零。
对于具体的down[x]的更新,只需要在getfather的时候递归操作即可。
CODE
#include<cstdio> using namespace std; const int N=30005; int down[N],len[N],father[N],n,p,i,x,y; char opt; inline void read(int &x) { x=0; int flag=1; char ch=getchar(); while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=getchar(); } while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); x*=flag; } inline void write(int x) { if (x<0) putchar('-'),x=-x; if (x/10) write(x/10); putchar(x%10+'0'); } inline int getfather(int k) { if (father[k]==k) return k; int fa=father[k]; father[k]=getfather(father[k]); down[k]+=down[fa]; return father[k]; } int main() { read(p); for (i=1;i<N;++i) father[i]=i,len[i]=1,down[i]=0; while (p--) { while (opt=getchar(),opt!='M'&&opt!='C') opt=getchar(); if (opt=='M') { read(x),read(y); int fx=getfather(x),fy=getfather(y); if (fx!=fy) { father[fx]=fy; down[fx]+=len[fy]; len[fy]+=len[fx]; len[fx]=0; } } else read(x),getfather(x),write(down[x]),putchar(' '); } return 0; }
2236:一道基础的并查集维护联通关系的题目。
每打开一台计算机,就扫描过其他所有的打开的计算机。如果他们之间的距离小于等于d就合并。
查询的时候并查集查询father即可。
CODE
#include<cstdio> using namespace std; const int N=1005; int x[N],y[N],n,d,father[N],i,num,a,b; bool vis[N]; char opt; inline void read(int &x) { x=0; char ch=getchar(); int flag=1; while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=getchar(); } while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); x*=flag; } inline int getfather(int k) { return father[k]==k?k:father[k]=getfather(father[k]); } int main() { read(n); read(d); for (i=1;i<=n;++i) read(x[i]),read(y[i]),father[i]=i; while (scanf("%c",&opt)!=EOF) { if (opt=='O') { read(num); if (vis[num]) continue; vis[num]=1; for (i=1;i<=n;++i) { if (num==i) continue; if (vis[i]&&(x[i]-x[num])*(x[i]-x[num])+(y[i]-y[num])*(y[i]-y[num])<=d*d) father[getfather(i)]=getfather(num); } } else { read(a); read(b); if (!vis[a]||!vis[b]) { puts("FAIL"); continue; } if (getfather(a)==getfather(b)) puts("SUCCESS"); else puts("FAIL"); } } return 0; }