結果

問題 No.5007 Steiner Space Travel
ユーザー titan23titan23
提出日時 2022-07-30 16:01:30
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 946 ms / 1,000 ms
コード長 3,747 bytes
コンパイル時間 249 ms
実行使用メモリ 144,032 KB
スコア 2,379,200
最終ジャッジ日時 2022-07-30 16:02:01
合計ジャッジ時間 31,095 ms
ジャッジサーバーID
(参考情報)
judge13 / judge15
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 935 ms
140,024 KB
testcase_01 AC 936 ms
141,952 KB
testcase_02 AC 936 ms
141,880 KB
testcase_03 AC 934 ms
139,436 KB
testcase_04 AC 938 ms
135,808 KB
testcase_05 AC 928 ms
140,952 KB
testcase_06 AC 928 ms
139,836 KB
testcase_07 AC 925 ms
139,992 KB
testcase_08 AC 937 ms
142,496 KB
testcase_09 AC 929 ms
139,476 KB
testcase_10 AC 927 ms
141,560 KB
testcase_11 AC 946 ms
141,460 KB
testcase_12 AC 940 ms
142,240 KB
testcase_13 AC 937 ms
139,952 KB
testcase_14 AC 936 ms
139,676 KB
testcase_15 AC 938 ms
139,720 KB
testcase_16 AC 936 ms
144,008 KB
testcase_17 AC 943 ms
139,524 KB
testcase_18 AC 926 ms
141,776 KB
testcase_19 AC 932 ms
139,920 KB
testcase_20 AC 931 ms
142,600 KB
testcase_21 AC 941 ms
140,788 KB
testcase_22 AC 932 ms
144,032 KB
testcase_23 AC 933 ms
140,968 KB
testcase_24 AC 937 ms
143,404 KB
testcase_25 AC 924 ms
141,520 KB
testcase_26 AC 940 ms
120,604 KB
testcase_27 AC 929 ms
139,900 KB
testcase_28 AC 929 ms
141,144 KB
testcase_29 AC 926 ms
139,876 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

import sys
import time
import random
import math
input = lambda: sys.stdin.readline().rstrip()

from collections import defaultdict
class UnionFind:

  def __init__(self, n: int):
    "Build a new UnionFind. / O(N)"
    self.__n = n
    self.__group_numbers = n
    self.__parents = [-1] * n

  def __find(self, x: int) -> int:
    a = x
    while self.__parents[a] >= 0:
      a = self.__parents[a]
    while self.__parents[x] >= 0:
      self.__parents[x] = a
      x = self.__parents[x]
    return a

  def unite(self, x: int, y: int) -> None:
    "Untie x and y. / O(α(N))"
    x, y = self.__find(x), self.__find(y)
    if x == y:
      return
    self.__group_numbers -= 1
    if self.__parents[x] > self.__parents[y]:
      x, y = y, x
    self.__parents[x] += self.__parents[y]
    self.__parents[y] = x

  def size(self, x: int) -> int:
    "xが属する集合の要素数. / O(α(N))"
    return -self.__parents[self.__find(x)]

  def same(self, x: int, y: int) -> bool:
    "Return True if 'same' else False. / O(α(N))"
    return self.__find(x) == self.__find(y)

  def roots(self) -> list:
    "Return all roots. / O(N)"
    return [i for i,x in enumerate(self.__parents) if x < 0]

  def group_count(self) -> int:
    "Return the number of groups. / O(1)"
    return self.__group_numbers

  def all_group_members(self) -> list:
    "Return all_group_members. / O(Nα(N))"
    group_members = defaultdict(list)
    for member in range(self.__n):
      group_members[self.__find(member)].append(member)
    return group_members

  def relax(self) -> None:
    "/relax."
    for i in range(self.__n):
      self.__find(i)

  def __str__(self) -> str:
    ret = '<UnionFind> [\n'
    ret += '\n'.join(f'  {k}: {v}' for k,v in self.all_group_members().items())
    ret += '\n]\n'
    return ret


#  -----------------------  #

n, m = map(int, input().split())
ab = [tuple(map(int, input().split())) for _ in range(n)]
ab_set = set(ab)
ALP = 5
LIMIT = 0.8
START = time.time()
 
def MST(E):
  uf = UnionFind(n+m+1)
  E.sort(key=lambda x: -x[2])
  used = []
  cost = 0
  for i,j,c in E:
    if uf.same(i, j):
      continue
    uf.unite(i, j)
    used.append((i, j))
    cost += c
  return cost, used

def make_stations():
  stations = []
  while len(stations) < m:
    i, j = random.randint(0, 1000), random.randint(0, 1000)
    if (i, j) in ab_set:
      continue
    stations.append((i, j))

  E = []
  for i in range(n+m):
    for j in range(n+m):
      if i == j:
        continue
      cost = 0
      if i < n:
        if j < n:
          cost = ALP * ALP * ((ab[i][0] - ab[j][0])**2 + (ab[i][1] - ab[j][1])**2)
        else:
          cost = ALP * ((ab[i][0] - stations[j-n][0])**2 + (ab[i][1] - stations[j-n][1])**2)
      else:
        if j < n:
          cost = ALP * ((stations[i-n][0] - ab[j][0])**2 + (stations[i-n][1] - ab[j][1])**2)
        else:
          cost = ((stations[i-n][0] - stations[j-n][0])**2 + (stations[i-n][1] - stations[j-n][1])**2)
      E.append((i+1, j+1, cost))
  score, mst = MST(E)
  return stations, score, mst

from collections import deque
def make_root(mst):
  G = [[] for _ in range(n+m+1)]
  for i,j in mst:
    G[i].append(j)
    G[j].append(i)
  ret = []
  seen = set([1])
  todo = deque([1])
  while todo:
    v = todo.popleft()
    ret.append(v)
    for x in G[v]:
      if x in seen: continue
      todo.append(x)
      seen.add(x)
  return ret

vestscore = float('inf')
ans = []
while time.time() - START < LIMIT:
  stations, score, mst = make_stations()
  if score < vestscore:
    vestscore = score
    ans = [stations[:], mst[:]]
root = make_root(ans[1])
for i in ans[0]:
  print(*i)
print(len(root)+1)
for i in root:
  if i <= n:
    print(1, i)
  else:
    print(2, i-n)
print(1, 1)
0