P1031 -- 无线网络
时间限制:1000MS 内存限制:65536KB
Description
有一个由n台计算机组成的无线网络。(n <= 1001) 正常情况下,每台计算机都能跟与它距离不超过d的任何计算机通讯。 (d <= 20000) 地震发生了。所有的计算机都陷入瘫痪。专家们试着一台一台地修复计算机,以恢复整个无线网络。有时在修复的过程中,他们需要测试一下某两台计算机能否通讯(如果他们能通过别的正常的计算机进行通讯,也算他们之间可以通讯,即"能否通讯"可以是间接的)。 你的任务,就是模拟修复网络的过程,并回答"能否通讯"的询问。
Input Format
第一行两个整数,N和d,N表示计算机的数目,d表示两台计算机直接可直接通讯的最大距离。接下来的N行,每行两个整数Xi,Yi,表示每台计算机的坐标。接下来有许多行,每行都是一个操作(或者是修复操作,或者是询问操作)。 操作的格式如下: O p (1 <= p <= N) 修复操作,表示修复编号为p的电脑; S p q (1 <= p, q <= N) 询问操作,询问编号为p和编号为q的电脑能否通讯。 如果一台电脑尚未被修复,则它不能和任何电脑通讯。
Output Format
对于每个询问操作:如果能够通讯,输出一行SUCCESS;如果无法通讯,输出一行FAIL
Sample Input
4 1 0 1 0 2 0 3 0 4 O 1 O 2 O 4 S 1 4 O 3 S 1 4
Sample Output
FAIL SUCCESS
Hint
对于50%的数据,N <= 300, 操作次数 <= 10000; 对于100%的数据,N <= 1001, 操作次数 <= 300000。
【题解】
此题一看到题目就想到用并查集(或许是最近并查集的题目做了挺多的)
反正就是并查集,路径压一压就好(事实证明这道题路径不压比压还好!!!)
然后就对于每个的O操作,1...n扫一遍,更新一下即可
然而看起来会超时,实际并不会。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,d; 4 int x[1002],y[1002],pre[1002]; 5 bool vis[1002]; 6 inline double getdist(int xz,int yz,int xy,int yy) {return sqrt((xz-xy)*(xz-xy)+(yz-yy)*(yz-yy));} 7 int findset(int x) { 8 int r=x; 9 while(pre[r]!=r) r=pre[r]; 10 int i=x,j; 11 while(i!=r) { 12 j=pre[i]; 13 pre[i]=r; 14 i=j; 15 } 16 return r; 17 } 18 int main() { 19 scanf("%d%d",&n,&d); 20 for (int i=1;i<=n;++i) pre[i]=i; 21 char cs[2]; 22 for (int i=1;i<=n;++i) scanf("%d%d",&x[i],&y[i]); 23 while(~scanf("%s",cs)) { 24 if (cs[0]=='S') { 25 int a,b; 26 scanf("%d%d",&a,&b); 27 int a1=findset(a),b1=findset(b); 28 if(a1==b1&&vis[a]&&vis[b]) printf("SUCCESS\n"); 29 else printf("FAIL\n"); 30 } 31 else { 32 int a; 33 scanf("%d",&a); 34 vis[a]=1; 35 for (int i=1;i<=n;++i) if(vis[i]&&i!=a&&getdist(x[a],y[a],x[i],y[i])<=d) pre[findset(i)]=findset(a); 36 } 37 } 38 return 0; 39 }