-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplanet_solution.py
123 lines (90 loc) · 2.88 KB
/
planet_solution.py
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import math
import os
import sys
import random
import time
from queue import LifoQueue
zearth_pos = tuple(map(float, input().rstrip().split()))
earth_pos = (0.0, 0.0, 0.0)
N = int(input())
M = 10000
stations = [tuple(map(float, input().rstrip().split())) for i in range(N)]
# helper function
def dist(u, v):
return math.sqrt( sum([ (u[i]-v[i])**2 for i in range(3) ]) )
def generate_samples(num_samples):
samples = [(random.uniform(-M,M), random.uniform(-M,M), random.uniform(-M,M))
for i in range(num_samples)]
return samples
def is_possible(C):
# Check if route is possible with max edge length C
d = {} # will store state for each station. 0 is unreached, 1 is visiting, 2 is visited
for station in stations:
d[station] = 0
d[earth_pos] = 1
visiting = LifoQueue()
visiting.put(earth_pos)
while(visiting.qsize() != 0):
here = visiting.get()
d[here] = 2
if(dist(here, zearth_pos) <= C):
return True
for station, value in d.items():
if(value == 0 and dist(here, station) <= C):
d[station] = 1
visiting.put(station)
return False
def capacity_scaling():
# capacity scaling, binary search approach (more interesting)
# C will be the max allowable distance. a and b are the search range
a, b = 0.0, dist(earth_pos, zearth_pos)+1.0
while(b-a >= 0.01):
C = (a+b)/2
possible = is_possible(C)
if(possible):
b = C
else:
a = C
# just need a bit of logic due to rounding
a = round(a, 2)
b = round(b, 2)
if(a == b):
ans = a
else:
if(is_possible( (a+b)/2 )):
ans = a
else:
ans = b
return ans
def kruskal():
stations.append(earth_pos)
stations.append(zearth_pos)
L = len(stations)
# list and sort all edges in the graph
edges = [(stations[i], stations[j]) for i in range(L) for j in range(i+1,L)]
edges = sorted(edges, key = lambda x : dist(x[0],x[1]))
parents = {s : s for s in stations}
# find root with path compression
def root(x):
if(parents[x] == x):
return x
else:
parents[x] = root(parents[x])
return parents[x]
# merges sets
def union(x, y):
root_x = root(x)
root_y = root(y)
if(root_x != root_y):
parents[root_x] = root_y
maximum = 0
for a, b in edges:
if(root(a) != root(b)):
maximum = dist(a, b)
union(a, b)
if(root(earth_pos) == root(zearth_pos)):
break
return round(maximum, 2)
# cap_ans = capacity_scaling()
kru_ans = kruskal()
sys.stdout.write(str(kru_ans))