Wireless Network POJ - 2236

题意:给你n台电脑的坐标,一个距离d,这个d的意思是如果两台电脑的距离小于等于d,那么他们可以连接在一起,其中a连b,b连c,那么c可以连a,起初这几台电脑都是坏的,之后给你一组操作,O a,表示修复a这台电脑(它可以和其他好的且距离小于d的电脑连接),S a b 是询问a和b这两台电脑是不是连接在一起,如果是输出成功,如果不是输出失败

思路:分析一下这道题,那就是我们现在有一堆电脑,在修复电脑a的过程中,如果他周围的电脑和a的距离小于d那么我们可以将他们连接在一起(),之后我们还要查找a,b是否连接,也就是说a,b是不是在一个集合里面(),嗯,没错裸的并查集,唯一有新意的地方就是在合并a,b的时候要看一下a和b是否都修复了并且a,b的距离是否比d小就好了,上代码吧:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <iostream>
using namespace std;
struct node 
{
	double x,y;
}edg[1101];
double dist[1101][1101] , vis[1101];
int p[1101];
int n,d;
int getf(int x)
{
	return x == p[x] ? x : p[x] = getf(p[x]);
}
void init()
{
	for(int i = 0 ; i < 1101 ; i++)
	{
		p[i] = i;
	}
}

void merge(int x,int y)
{
	int dx = getf(x);
	int dy = getf(y);
	//printf("P = %lf\n",distc(edg[x],edg[y]));
		if(dx != dy)
		{
		//	printf("dx = %d dy = %d\n",dx,dy);
			p[dy] = dx;
		}
	
}
int main()
{
	
	while(scanf("%d%d",&n,&d)!=EOF)
	{
		init();
		for(int i = 1 ; i <= n ; i++)
		{
			scanf("%lf%lf",&edg[i].x,&edg[i].y);
		}
		for(int i = 1 ; i <= n ; i++)//先把所有的距离都打到一个表上 
		{
			for(int j = 1 ; j <= n ;j++)
			{
				dist[i][j] = sqrt((edg[i].x-edg[j].x) * (edg[i].x-edg[j].x) + (edg[i].y - edg[j].y) * (edg[i].y - edg[j].y));
			}
		}
		char op[3];
		memset(vis,0,sizeof(vis));
		while(scanf("%s",op)!=EOF)
		{
			int a,b;
			if(op[0] == 'O')
			{
				scanf("%d",&a);
				vis[a] = 1;//如果a修复了就打上标记 
				for(int i = 1 ; i <= n ; i++)
				{
					if(vis[i] && i!=a)//如果i也被修复了且i和a的距离小于等于d就表明他们可以合并到一个集合里 
					{
						if(dist[i][a] <= d)
						{
							merge(a,i);
						}
					}
				}
			}
			else 
			{
				scanf("%d%d",&a,&b);
				if(getf(a) == getf(b))
				{
					puts("SUCCESS");
				}
				else 
				{
					puts("FAIL");
				}
			}
		}
	}
	
}
这是把所有距离都打成表的写法,其实没必要打个一个表,在合并的时候判断一下就好了,也都一样,

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <iostream>
using namespace std;
struct node 
{
	double x,y;
}edg[1101];
double dist[1101][1101] , vis[1101];
int p[1101];
int n,d;

double distc(node a,node b)
{
    double dist;
    dist=sqrt((double)((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)));
    return dist;
}

int getf(int x)
{
	return x == p[x] ? x : p[x] = getf(p[x]);
}
void init()
{
	for(int i = 0 ; i < 1101 ; i++)
	{
		p[i] = i;
	}
}

void merge(int x,int y)
{
	int dx = getf(x);
	int dy = getf(y);
	if(distc(edg[x],edg[y]) <= d)
	{
		if(dx != dy)
		{
			p[dy] = dx;
		}
	}
	
}
int main()
{
	
	while(scanf("%d%d",&n,&d)!=EOF)
	{
		init();
		for(int i = 1 ; i <= n ; i++)
		{
			scanf("%lf%lf",&edg[i].x,&edg[i].y);
		}
		char op[3];
		memset(vis,0,sizeof(vis));
		while(scanf("%s",op)!=EOF)
		{
			int a,b;
			if(op[0] == 'O')
			{
				scanf("%d",&a);
				vis[a] = 1;
				for(int i = 1 ; i <= n ; i++)
				{
					if(vis[i] && i!=a)
					merge(a,i);
				}
			}
			else 
			{
				scanf("%d%d",&a,&b);
				if(getf(a) == getf(b))
				{
					puts("SUCCESS");
				}
				else 
				{
					puts("FAIL");
				}
			}
		}
	}
	
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值