1. 程式人生 > >poj2236 並查集板子題

poj2236 並查集板子題

題目大意:

  給你N臺電腦和一個距離D,然後給你N臺電腦的座標xi,yi,0<=xi,yi<=10000,d<=20000,給你最多3e5次查詢,每次查詢中,(O x)表示修復了x號電腦,(S x y)表示詢問x和y是否可以通訊,返回查詢結果(如果兩臺電腦距離在d之內,那麼兩臺電腦可以相連)

題解:

  一共3e5次查詢,但是最多有1000個點,所以最多修復1000臺電腦,列舉所有電腦,找到他周圍可以連線的電腦,進行合併(一開始想的是,如果修復3e5次,直接時間爆炸,不過後來發現最多修1e3次,傻了。。。)給了10s,直接水過

  不知道為啥我開始想的時候是在連線的時候就進行合併,然後修復的時候再找邊,一定是失了智。。。

貼上程式碼:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #define mem(a,b) memeset(a,b,sizeof(b))
 5 using namespace std;
 6 const int maxn=1e3+10;
 7 int parent[maxn],vis[maxn],rank[maxn];
 8 int d,n;
 9 struct node
10 {
11     int x,y;
12     node(){}
13     node(int
a,int b):x(a),y(b){} 14 }pc[maxn]; 15 double len(node a,node b) 16 { 17 int x=a.x-b.x; 18 int y=a.y-b.y; 19 return sqrt(x*x+y*y); 20 } 21 int find(int x) 22 { 23 int k, j, r; 24 r = x; 25 while(r != parent[r]) 26 r = parent[r]; 27 k = x; 28 while(k != r) 29 {
30 j = parent[k]; 31 parent[k] = r; 32 k = j; 33 } 34 return r; 35 } 36 void merg(int x,int y) 37 { 38 int fx=find(x); 39 int fy=find(y); 40 if(rank[fx]<=rank[fy]) 41 { 42 parent[fy]=fx; 43 rank[fx]++; 44 } 45 else 46 { 47 parent[fx]=fy; 48 rank[fy]++; 49 } 50 } 51 void ini() 52 { 53 for(int i=1;i<=maxn;i++) parent[i]=i; 54 } 55 int main() 56 { 57 ini(); 58 scanf("%d%d",&n,&d); 59 for(int i=1;i<=n;i++) 60 { 61 scanf("%d%d",&pc[i].x,&pc[i].y); 62 } 63 char s; 64 while(cin>>s) 65 { 66 int a,b; 67 if(s=='O') 68 { 69 scanf("%d",&a); 70 if(vis[a]) continue; 71 vis[a]=1; 72 for(int i=1;i<=n;i++) 73 { 74 if(a==i) continue; 75 if(len(pc[a],pc[i])>d) continue; 76 if(!vis[i]) continue; 77 else merg(a,i); 78 } 79 /*for(int i=1;i<=n;i++) 80 { 81 printf("%d ",parent[i]); 82 }puts("\n");*/ 83 } 84 else 85 { 86 scanf("%d%d",&a,&b); 87 int fa=find(a); 88 int fb=find(b); 89 if(fa==fb) printf("SUCCESS\n"); 90 else printf("FAIL\n"); 91 } 92 } 93 return 0; 94 }
View Code