HIT2064 Journey to Tibet(求无向图中点权之和最大的连通分量)

题目链接:

  http://acm.hit.edu.cn/hoj/problem/view?id=2064

 

题目描述:

Journey to Tibet

 
 

Submitted : 459, Accepted : 184

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

题目大意:

  无向图,每个点上有权值,给出点在二维平面上的坐标,距离不大于30的点互相连通。求连通分量的最大权值之和

思路:

  重要是读题……开始一直以为是一道图的最长路,但后来发现一个村子可以通过无数遍,且时间无限,但点权只能加一次

  先建图,注意直接 A^2 + B^2 <= 900 不要开方,速度快且不容易被卡精度

  然后扫每个点,如果未处于同一个连通分量中,则dfs求解

  注意因为从小往大扫所以自动可以保证点的标号最小。

 

代码:

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <utility>
 6 using namespace std;
 7 
 8 const int N = 1010;
 9 const int D = 900;
10 
11 typedef pair<int, int> pii;
12 
13 struct Edge {
14     int v, next;
15     Edge(int v = 0, int next = 0) :v(v), next(next) {}
16 }e[N*N];    //链式前向星
17 
18 int n, val[N], head[N], res, ans, id;
19 pii input[N];    //点坐标
20 bool vis[N];
21 
22 inline bool ok(int a, int b) {    //判断一天内能否到达,即两点之间是否有边
23     if (a == b)return false;
24     return (input[a].first - input[b].first)*(input[a].first - input[b].first) +
25         (input[a].second - input[b].second)*(input[a].second - input[b].second) <= D;
26 }
27 
28 inline void addedge(int u, int v) {
29     e[++id].v = v;
30     e[id].next = head[u];
31     head[u] = id;
32 }
33 
34 int dfs(int u) {    //求无向图中点权之和最大的连通分量
35     int sum = val[u];
36     for (int i = head[u]; i; i = e[i].next)
37         if (!vis[e[i].v]) {
38             vis[e[i].v] = true;
39             sum += dfs(e[i].v);
40         }
41     return sum;
42 }
43 
44 int main() {
45     while (cin >> n&&n) {
46         ans = id = 0, res = 1;
47         memset(vis, 0, sizeof(vis));
48         memset(head, 0, sizeof(head));
49         for (int i = 1; i <= n; ++i)
50             scanf("%d%d%d", &input[i].first, &input[i].second, &val[i]);
51         for (int i = 1; i < n; ++i)
52             for (int j = i + 1; j <= n; ++j)
53                 if (ok(i, j))addedge(i, j), addedge(j, i);
54         for (int i = 1; i <= n; ++i)if (!vis[i]) {
55             vis[i] = true;
56             int tmp = dfs(i);
57             if (tmp > ans) { ans = tmp; res = i; }
58         }
59         printf("%d %d\n", res, ans);
60     }
61 }

 

posted @ 2017-06-09 15:57  hyp1231  阅读(296)  评论(0编辑  收藏  举报