作者:沉醉不知归路1222 | 来源:互联网 | 2023-10-10 15:07
并查集的一个很重要的特性是传递性,如可以从a可以到b,从b可以到c,那么从a可以到c,如果满足这个的条件,要求一些特定的集合判定,属于那些集合,大多都属于并查集poj2236题意很
并查集的一个很重要的特性是传递性,如可以从a可以到b,从b可以到c,那么从a可以到c,如果满足这个的条件,要求一些特定的集合判定,属于那些集合,大多都属于并查集
poj2236
题意很简明::::
在一次地震中有n台电脑被损坏了,然后给出这n台电脑的坐标!
随后给出多组询问,以0开头就表示修理好这台电脑,如果是s就表示求两台电脑之间能否通讯
通讯的条件是两台电脑距离小于等于d且具有传递性 如a能和b通信,b能和c通信,然后a便能和c通信
一个要注意的一点是给出的欧几里得距离,但是这些坐标都是整数,所以可以用他们的平方来表示(而且最重要的一点是他们的平方并不大,以后碰到这种题目也可以朝这方面去想,因为这样可以保证不会出现精度问题,前提是不会爆long long)
从那个传递性来看的话可以考虑并查集(并查集是看一些元素是不是在一个联通分量里面的,而传递性正是联通分量的一种特性),但是没输入一台电脑,怎么把它维护与其他的关系呢
这样就只能暴力了,一开始一直没看时间复杂度,导致没敢暴力,这是问题啊。
以后看题一定是看出问题的模型,问题的本质,分析一下数据,然后看一下时空复杂度,而且还要对证一下样例,最后对证一些特值,
下面给出代码
1 #include
2 #include
3 #include
4 #include
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 }
View Code
并查集---------kuangbin带你飞合集