POJ 2236 Wireless Network

题目大意:
        现只有一个测例,有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, 笔记本电脑

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值