并查集 HOJ 2064 Journey to Tibet

Journey to Tibet

My Tags   (Edit)
Source : HCPC 2005 FALL
Time limit : 1 sec Memory limit : 32 M

Submitted : 410, Accepted : 162

After having to reinstall your computer 42 times on the same day, you decided to take a short break -- you will spend the next 5 years (or more) in Tibet. The population of China is very unevenly distributed: in the eastern coastal areas the population density can be above 400 people per square kilometer, while in the western plateaus there are less then 10 people per square kilometer. However, Tibet, where 2.3 million people share 1.2 million square kilometers, is by far the most sparsely populated place in China. You hope that in the small villages and monasteries of Tibet, no one will ask you to fix their computer.

But which village should you choose? Looking at the map of Tibet, you see a large number of interesting places. You want to go to a place where you can visit many monasteries. Each village has a number of monasteries. Your plan is that you go from village to village to visit as many monasteries as possible. However, you can only travel 30 kilometers a day, and it is not safe to spend the night in the wilderness. Thus, depending on your initial position, you can visit only some of the villages. Therefore, you have to choose your initial position (the village where you start your holiday) carefully, if you want to maximize the number of monasteries that can be visited.

A final note: Tibet enjoys(or, say, suffers) an average of 3,000 hours of sunshine a year, so don't forget your sun glasses and suntan cream!

Input

The input contains several blocks of test cases. Each case begins with a line containing an integer 1 ≤ n ≤ 1000, the number of villages. The next n lines contains three integers each: the two coordinates of the village (in kilometers), and the number of monasteries in the village. The villages are numbered from 1 to n, in the order that they appear in the input. The coordinates are between 0 and 20000, and the number of monasteries in a village is at most l000. The input is terminated by a block with 0 villages.

Output

For each test case you have to output two integers on a line (separated by a single space). The first integer identifies the village where you want to go (this number is between 1 and n), and the second integer is the number of monasteries that can be visited starting from this location. If there is more than one village that maximizes the number of reachable monasteries, choose the one that has the smallest index (you know, we problemsetters hate to write any special judge).

Input

6
100 100 8
0 0 10
0 10 3
10 30 4
1000 1000 4
100 128 3
0
Sample Output
2 17

题意:选出一个起点,然后从这个起点开始一次只能走30km,问最多能访问多少的寺庙。

思路:其实就是求出一个含有寺庙最多的连通块,并且选取这个连通块中标号最小的点作为起点。这里连通块我们用并查集实现。

代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define eps 1e-6
#define mp make_pair
#define pb push_back
const int maxn = 1000+10;
int n;

vector son[maxn];
int p[maxn];
int num[maxn];

int find(int x)
{
if (x==p[x]) return x;
return p[x] = find(p[x]);
}

void Union(int rt1,int rt2)
{
int x = find(rt1);
int y = find(rt2);
if (x==y) return;
if (x < y) p[y] = x;
else p[x] = y;
}

struct Node
{
int x , y;
}node[maxn];

void init()
{
for (int i = 1 ; i <= n ; ++i)
{
son[i].clear();
p[i] = i;
}
}

inline int sqr(int x)
{
return x*x;
}

inline int cal_dis(int i,int j)
{
return sqr(node[i].x-node[j].x)+sqr(node[i].y-node[j].y);
}

void input()
{
for (int i = 1 ; i <= n ; ++i) 
{
scanf("%d%d%d",&node[i].x,&node[i].y,num+i);
}
for (int i = 1 ; i < n ; ++i)
{
for (int j = i+1 ; j <= n ; ++j)
{
int dis = cal_dis(i,j);
if (dis > 900) continue;
Union(i,j);
}
}
}

void solve()
{
for (int i = 1 ; i <= n ; ++i)
{
int fa = find(i);
son[fa].push_back(i);
}
int ans = 0 , sum , p;
for (int i = 1 ; i <= n ; ++i)
{
sum = 0;
int pp = i;
for (int j = 0 ; j < son[i].size() ; ++j)
{
pp = min(pp,son[i][j]);
sum += num[son[i][j]];
}
if (sum > ans)
{
ans = sum;
p = pp;
}
else if (ans==sum && pp < p) p = pp;
}
printf("%d %d\n",p,ans);
}

int main()
{
while (scanf("%d",&n),n)
{
init();
input();
solve();
}
}

你可能感兴趣的:(并查集)