并查集的一个很重要的特性是传递性,如可以从a可以到b,从b可以到c,那么从a可以到c,如果满足这个的条件,要求一些特定的集合判定,属于那些集合,大多都属于并查集
poj2236
题意很简明::::
在一次地震中有n台电脑被损坏了,然后给出这n台电脑的坐标!
随后给出多组询问,以0开头就表示修理好这台电脑,如果是s就表示求两台电脑之间能否通讯
通讯的条件是两台电脑距离小于等于d且具有传递性 如a能和b通信,b能和c通信,然后a便能和c通信
一个要注意的一点是给出的欧几里得距离,但是这些坐标都是整数,所以可以用他们的平方来表示(而且最重要的一点是他们的平方并不大,以后碰到这种题目也可以朝这方面去想,因为这样可以保证不会出现精度问题,前提是不会爆long long)
从那个传递性来看的话可以考虑并查集(并查集是看一些元素是不是在一个联通分量里面的,而传递性正是联通分量的一种特性),但是没输入一台电脑,怎么把它维护与其他的关系呢
这样就只能暴力了,一开始一直没看时间复杂度,导致没敢暴力,这是问题啊。
以后看题一定是看出问题的模型,问题的本质,分析一下数据,然后看一下时空复杂度,而且还要对证一下样例,最后对证一些特值,
下面给出代码
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=1100; 7 int n,d; 8 struct point{ 9 int x,y; 10 }; 11 point pt[2010]; 12 char cr; 13 int a,b; 14 int f[2010]; 15 int vis[2010]; 16 17 int find(int k){ 18 if(f[k]==-1) return k; 19 else return f[k]=find(f[k]); 20 } 21 22 bool join(int s,int e){ 23 return (pt[s].x-pt[e].x)*(pt[s].x-pt[e].x)+(pt[s].y-pt[e].y)*(pt[s].y-pt[e].y)<=d*d; 24 } 25 26 int main(){ 27 scanf("%d%d",&n,&d); 28 for(int i=1;i<=n;i++) scanf("%d%d",&pt[i].x,&pt[i].y); 29 for(int i=1;i<=n;i++) f[i]=-1; 30 memset(vis,0,sizeof(vis)); 31 while(scanf("\n%c",&cr)!=EOF){ 32 if(cr==‘S‘){ 33 scanf("%d%d",&a,&b); 34 int t1=find(a),t2=find(b); 35 if(t1!=t2) printf("FAIL\n"); 36 else printf("SUCCESS\n"); 37 }else{ 38 scanf("%d",&a); 39 vis[a]=1; 40 for(int i=1;i<=n;i++){ 41 if(vis[i]==1&&i!=a){ 42 int t1=find(i),t2=find(a); 43 if(t1==t2) continue; 44 if(join(i,a)) f[t1]=t2; 45 } 46 } 47 } 48 } 49 return 0; 50 }
原文地址:https://www.cnblogs.com/pandaking/p/9898554.html
时间: 2024-11-17 00:29:48