UVa 12860 - Galaxy collision

contents

  1. 1. Problem
  2. 2. Sample Input
  3. 3. Sample Output
  4. 4. Solution

Problem

給兩個星座,這兩個星座分別由很多個星星構成,並且在同一個星座的星星之間必須間隔至少大於 5 (歐幾里得距離)。

求其中一個星座最少有幾顆星星。保證輸入一定可以構成兩個星座。

Sample Input

1
2
3
4
5
6
7
8
9
10
6
1 3
9 1
11 7
5 7
13 5
4 4
2
10 10
50 30

Sample Output

1
2
2
0

Solution

看到兩個星座,就很像二分圖,把距離小於等於 5 的點之間連起來,接著二分圖黑白染色,對於每一個連通子圖會得到兩個集合。

根據貪心算法,將每一個連通圖的最小集合加總即可。

但是為了要快速建表,猜測輸入不會太集中,這會造成無法構成兩個星座,因此把圖根據 x 座標儲存,這麼一來只要搜索 [x-5, x+5] 之間的點集即可。

生測資也挺痛苦的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <set>
#include <queue>
using namespace std;
vector<int> g[65536];
vector< pair<int, int> > X[524288];
void buildGraph(int x) {
int d;
for (int i = X[x].size() - 1; i >= 0; i--) {
int y = X[x][i].first, u = X[x][i].second;
for (int j = x - 5; j <= x + 5; j++) {
if (j < 0) continue;
int st = (int)(lower_bound(X[j].begin(), X[j].end(), make_pair(y - 5, -1)) - X[j].begin());
for (int k = st; k < X[j].size(); k++) {
if (X[j][k].first > y + 5) break;
d = (x-j) * (x-j) + (X[j][k].first - y) * (X[j][k].first - y);
// d = abs(x-j) + abs(X[j][k].first - y);
if (d <= 25) {
if (u != X[j][k].second) {
g[u].push_back(X[j][k].second);
// printf("%d -> %d\n", u + 1, X[j][k].second + 1);
}
}
}
}
}
}
int visited[65536], dist[65536];
int bfs(int st) {
queue<int> Q;
int o[2] = {}, u, v;
Q.push(st), dist[st] = 1, visited[st] = 1;
while (!Q.empty()) {
u = Q.front(), Q.pop();
o[dist[u]&1]++;
for (int i = 0; i < g[u].size(); i++) {
v = g[u][i];
if (visited[v] == 0) {
dist[v] = dist[u] + 1;
visited[v] = 1;
Q.push(v);
}
}
}
return min(o[0], o[1]);
}
int main() {
int n, x, y;
while (scanf("%d", &n) == 1) {
set<int> S;
for (int i = 0; i < n; i++) {
scanf("%d %d", &x, &y);
X[x].push_back(make_pair(y, i));
S.insert(x);
visited[i] = 0;
g[i].clear();
}
for (set<int>::iterator it = S.begin();
it != S.end(); it++)
sort(X[*it].begin(), X[*it].end());
for (set<int>::iterator it = S.begin();
it != S.end(); it++)
buildGraph(*it);
int ret = 0;
for (int i = 0; i < n; i++)
if (visited[i] == 0)
ret += bfs(i);
printf("%d\n", ret);
for (set<int>::iterator it = S.begin();
it != S.end(); it++) {
X[*it].clear();
}
}
return 0;
}
/*
3
1 1
2 2
9 9
2
1 1
2 2
6
1 3
9 1
11 7
5 7
13 5
4 4
2
10 10
50 30
*/