题目大意:
地震啦,电脑的通信坏了,但是正在修理 —— 输入 “ O 1”,表示1号电脑被修好了 ,输入“ S 1 2 ” 表示询问这两台电脑能不能通讯。规定两台电脑之间的距离小于等于d的时候才能通讯,如果A,B能通讯,B能跟C通讯,那么A也能跟C通讯。第一行输入N, d,N表示有几台电脑,d表示最长距离。接下来N行,第i行表示第i台电脑的坐标。接下来输入操作。询问的时候输出“SUCCESS”或者“FAIL”。(输入行数不超过三万行)
参考思路:
自己的: 输入一个修理成功的电脑,把他存起来,和前面那些已经修好的电脑判断一下,判断条件是:1、已经修好的;2、距离小的。连接过了之后碰到询问的时候,就看看这两个点的根结点是不是一样。
参考代码:
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <queue>
#include <stack>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
using namespace std;
const int INF=0x3f3f3f3f;
const int SIZE=1e3+10;
struct node{
int id;
int fix; ///是否被修好?
double x,y;
}cmt[SIZE] ;
int sz[SIZE];
int n;
double d;
///要把电脑连接起来。
double dis(int p,int q)
{
double temp=(cmt[p].x-cmt[q].x)*(cmt[p].x-cmt[q].x)+(cmt[p].y-cmt[q].y)*(cmt[p].y-cmt[q].y); ///距离
return temp;
}
int find(int x)
{
while(cmt[x].id!=x)
{
cmt[x].id=cmt[cmt[x].id].id;
x=cmt[x].id;
}
return x; ///寻找根节点
}
bool connect(int p,int q)
{
return find(p)==find(q);
}
void un(int p,int q)
{
if(cmt[q].fix==0||dis(p,q)>d*d) return; ///没修过?距离太大?
int pr=find(p);
int qr=find(q);
if(pr==qr) return ; ///根节点已经相同
if(sz[pr]<sz[qr]) {sz[qr]+=sz[pr];cmt[pr].id=qr;}
else {sz[pr]+=sz[qr];cmt[qr].id=pr;}//cout<<"UN:"<<cmt[]<<" "<<sz[q]<<endl;
}
void clear()
{
for(int i=1;i<=n;i++)
sz[i]=1;
}
int main()
{
int i,j;
cin>>n>>d;
clear();
for(i=1;i<=n;i++)
{
cin>>cmt[i].x>>cmt[i].y;
cmt[i].fix=0;
cmt[i].id=i;
}
char x;
int temp,a,b;
while(cin>>x)
{
if(x=='O')
{
cin>>temp;
cmt[temp].fix=1; ///修过啦
for(i=1;i<=n;i++)
if(i!=temp)
un(temp,i);
}
else
{
cin>>a>>b;
if(!connect(a,b)) cout<<"FAIL\n";
else cout<<"SUCCESS\n";
}
}
return 0;
}
///http://blog.csdn.net/dm_vincent/article/details/7655764 (并查集相关)