题目链接:POJ2236ワイヤレスネットワーク
の制限時間:10000MSメモリ制限:65536kも
合計提出:49928受理:20443
説明
アンの地震が東南アジアで行われます。ACM(アジア間連携医療チーム)がラップコンピュータとワイヤレスネットワークを設定しましたが、予想外の余震は攻撃、ネットワーク内のすべてのコンピュータがすべて壊れていました。コンピュータは、一つ一つを修復され、そしてネットワークが徐々に再び仕事を始めました。なぜならハードウェア制限しにより、各コンピュータは、直接遠いそれからDメートル以下であるコンピュータと通信することができます。しかし、すべてのコンピュータは、コンピュータAとコンピュータBが直接通信できる場合、コンピュータAとコンピュータBが通信することができると言うことであるか、またはその両方Aと通信することができるコンピュータ・Cが2台の他のコンピュータとの間の通信の仲介、とみなすことができるとB.
2台のコンピュータが通信できる場合は、ネットワークを修復する過程では、労働者は、すべての瞬間において業務の2種類を取り、コンピュータを修理、またはテストすることができます。あなたの仕事は、すべてのテスト作業に答えることです。
入力は、
最初の行は二つの整数NおよびD(1 <= Nを<= 1001 0 <= D <= 20000)を含みます。ここでNは、1からNまで番号付けされているコンピュータの数であり、Dは、2台のコンピュータが直接通信可能な最大距離です。次のNラインにおいて、それぞれがN個のコンピュータの座標を2つの整数のXI、YI(0 <= XI、YI <= 10000)を含みます。(N + 1)番目の行からの入力の終わりに、一枚ずつ行われる動作があります。各行は、次の2つの形式のいずれかでの操作が含まれています。
- 「OのP」(1 <= p <= N)、コンピュータpを修復する手段。
- 「SのPQ」(1 <= P、Q <= N)、コンピュータpおよびqが通信できるかどうかをテストする手段。
入力は300000行を超えることはありません。
出力
各テスト動作の場合は、2台のコンピュータが通信できる場合、「SUCCESS」を印刷し、または「FAIL」ではない場合。
サンプル入力
4 1
0 1
0 2
0 3
0 4
O 1
O 2
O 4
S 1 4
O 3
S 1 4
サンプル出力
FAIL
SUCCESS
プログラムの説明:
互いに素なセット、サイクルすべてのコンピュータのコンピュータを修理するたびに、距離dを固定するためには、合成よりも小さいです。
また、そのスペースとキャリッジリターンを注意したときに入力(なぜなら、長い時間のためのこの小さなカードの詳細...)
コードは以下の通りであります:
#include <iostream>
#include <cstdio>
#define MAX 1001
using namespace std;
struct point {
int x, y;
} p[MAX + 1];
//par数组记录根,rank数组记录树的高度,vis数组标记是否已经修好
int par[MAX + 1], rank[MAX + 1], vis[MAX + 1];
int n, d, dis;
void init() {
for(int i = 1; i <= n; i++) {
par[i] = i;
rank[i] = 0;
vis[i] = 0;
}
}
int find(int x) {
if(par[x] == x)
return x;
else
return par[x] = find(par[x]);
}
void merge(int x1, int y1) {
dis = (p[x1].x - p[y1].x) * (p[x1].x - p[y1].x) + (p[x1].y - p[y1].y) * (p[x1].y - p[y1].y);
x1 = find(x1);
y1 = find(y1);
if(x1 == y1)
return;
if(rank[x1] < rank[y1] && dis <= d * d)
par[x1] = y1;
else if(rank[x1] >= rank[y1] && dis <= d * d){
par[y1] = x1;
if(rank[x1] == rank[y1])
rank[x1]++;
}
}
bool same(int x, int y) {
return find(x) == find(y) ? true : false;
}
int main() {
scanf("%d%d", &n, &d);
init();
char ch[2];
for(int i = 1; i <= n; i++) {
scanf("%d%d", &p[i].x, &p[i].y);
}
while(~scanf("%s", ch)) {
if(ch[0] == 'O') {
int k;
scanf("%d", &k);
vis[k] = 1;
for(int i = 1; i <= n; i++) {
//不在一个集合里并且已经被修好了
if(!same(i, k) && i != k && vis[i] == 1) {
merge(i, k);
}
}
}
else {
int p, q;
scanf("%d%d", &p, &q);
if(same(p, q))
//在同一个集合里
printf("SUCCESS\n");
else
printf("FAIL\n");
}
}
return 0;
}
チャー変数CHを宣言する前に、しかし吸収バッファのscanfによる正しく出力できない改行、スペースをもたらすであろう。変更後の次のコードは、上記の問題に対する有効なソリューションを提供します。
#include <iostream>
#include <cstdio>
#define MAX 1001
using namespace std;
struct point {
int x, y;
} p[MAX + 1];
//par数组记录根,rank数组记录树的高度,vis数组标记是否已经修好
int par[MAX + 1], rank[MAX + 1], vis[MAX + 1];
int n, d, dis;
void init() {
for(int i = 1; i <= n; i++) {
par[i] = i;
rank[i] = 0;
vis[i] = 0;
}
}
int find(int x) {
if(par[x] == x)
return x;
else
return par[x] = find(par[x]);
}
void merge(int x1, int y1) {
dis = (p[x1].x - p[y1].x) * (p[x1].x - p[y1].x) + (p[x1].y - p[y1].y) * (p[x1].y - p[y1].y);
x1 = find(x1);
y1 = find(y1);
if(x1 == y1)
return;
if(rank[x1] < rank[y1] && dis <= d * d)
par[x1] = y1;
else if(rank[x1] >= rank[y1] && dis <= d * d){
par[y1] = x1;
if(rank[x1] == rank[y1])
rank[x1]++;
}
}
bool same(int x, int y) {
return find(x) == find(y) ? true : false;
}
int main() {
scanf("%d%d", &n, &d);
init();
char ch;
for(int i = 1; i <= n; i++) {
scanf("%d%d", &p[i].x, &p[i].y);
}
while(~scanf("%c", &ch)) {
if(ch == 'O') {
int k;
scanf("%d", &k);
vis[k] = 1;
for(int i = 1; i <= n; i++) {
//不在一个集合里并且已经被修好了
if(!same(i, k) && i != k && vis[i] == 1) {
merge(i, k);
}
}
}
else if(ch == 'S'){
int p, q;
scanf("%d%d", &p, &q);
if(same(p, q))
//在同一个集合里
printf("SUCCESS\n");
else
printf("FAIL\n");
}
}
return 0;
}