题目大意:
现只有一个测例,有N台(1 ≤ N ≤ 1001)台电脑(编号1 ~ N),以及任意两台电脑之间的最大通信距离D(0 ≤ D ≤ 20,000),接下来按照编号从小到大给出每台电脑的位置坐标(xi, yi),其中0 ≤ xi, yi ≤ 10,000),接着有很多询问(询问以EOF结束),询问共有两种形式,一种是"O p",表示修好编号为p的电脑,另一种是"S p q",表示要求你输出编号p和q的两台电脑之间能否相互通信,能输出"SUCCESS"否则输出"FAIL"。
注意:只有修好的电脑才能参与通信活动,两台电脑能通信的两种情况是,两台电脑距离小于等于D则可直接通信,或者两电脑通过中间的电脑间接通信。
注释代码:
/*
* Problem ID : POJ 2236 Wireless Network
* Author : Lirx.t.Una
* Language : C++
* Run Time : 954 ms
* Run Memory : 252 KB
*/
#include <iostream>
#include <cstdio>
#include <vector>
//最大电脑数
#define MAXN 1001
using namespace std;
int d;//通信最大间距限制
struct Point {//电脑的坐标
int x, y;
friend istream &
operator>>( istream &is, Point &p ) {
is >> p.x >> p.y;
return is;
}
int
dpow(int x) {
return x * x;
}
bool
operator^(Point &oth) {//计算两点距离是否超出d
if ( dpow( x - oth.x ) + dpow( y - oth.y ) <= dpow(d) )
return true;//未超出
return false;//超出
}
};
Point p[MAXN + 1];//点
int fath[MAXN + 1];//并查集
vector<int> rpd;//repaired computers,存放修好的电脑的容器
//存放的是电脑的编号
int
find(int x) {
return x == fath[x] ? x : ( fath[x] = find( fath[x] ) );
}
void
merge( int a, int b ) {
int fa, fb;
fa = find(a);
fb = find(b);
fath[fb] = fa;
}
int
main() {
int n;//电脑数量
int u, v;//临时接受电脑的编号
int i;//计数变量
char cmd;//操作命令
scanf("%d%d", &n, &d);
for ( i = 1; i <= n; i++ ) {//初始化
fath[i] = i;
cin >> p[i];
}
while ( ~scanf("\n%c", &cmd) )
switch (cmd) {
case 'O' :
scanf("%d", &u);//修好u
rpd.push_back(u);//将u假如好电脑的容器
//逐个检查,和修好的电脑并入一个集合
//!!!注意:必须每台都检查,因为有可能出现这种情况
//比如容器里有2 3 4,现在进来一个7,7和2 3 4都距离太远不能通信
//因此容器现在又2 3 4 7,但是2 3 4在一个集合中(表示可以互通),而7单独在一个集合中
//但是7也是太好电脑
//现在进来一个5,5不仅能和3互通也和7的距离小于D,因此5可以作为媒介,将7和3所在集合合并
//因此进来的5必须和2 3 4 7逐个合并,防止7被漏掉!!!
for ( i = 0; i < rpd.size() - 1; i++ ) {//最后是自己,因此不用检查
v = rpd[i];
if ( u != v && p[u] ^ p[v] )
merge( u, v );
}
break;
case 'S' :
scanf("%d%d", &u, &v);
if ( find(u) == find(v) ) puts("SUCCESS");
else puts("FAIL");
break;
default : break;
}
return 0;
}
无注释代码:
#include <iostream>
#include <cstdio>
#include <vector>
#define MAXN 1001
using namespace std;
int d;
struct Point {
int x, y;
friend istream &
operator>>( istream &is, Point &p ) {
is >> p.x >> p.y;
return is;
}
int
dpow(int x) {
return x * x;
}
bool
operator^(Point &oth) {
if ( dpow( x - oth.x ) + dpow( y - oth.y ) <= dpow(d) )
return true;
return false;
}
};
Point p[MAXN + 1];
int fath[MAXN + 1];
vector<int> rpd;
int
find(int x) {
return x == fath[x] ? x : ( fath[x] = find( fath[x] ) );
}
void
merge( int a, int b ) {
int fa, fb;
fa = find(a);
fb = find(b);
fath[fb] = fa;
}
int
main() {
int n;
int u, v;
int i;
char cmd;
scanf("%d%d", &n, &d);
for ( i = 1; i <= n; i++ ) {
fath[i] = i;
cin >> p[i];
}
while ( ~scanf("\n%c", &cmd) )
switch (cmd) {
case 'O' :
scanf("%d", &u);
rpd.push_back(u);
for ( i = 0; i < rpd.size() - 1; i++ ) {
v = rpd[i];
if ( u != v && p[u] ^ p[v] )
merge( u, v );
}
break;
case 'S' :
scanf("%d%d", &u, &v);
if ( find(u) == find(v) ) puts("SUCCESS");
else puts("FAIL");
break;
default : break;
}
return 0;
}
单词解释:
aftershock:n, 余震
earthquake:n, 地震,大动荡
intermediary:n, 中间人,媒介
lap:n, 膝盖
laptop:n, 笔记本电脑