백준 문제풀이

백준 1396 - 크루스칼의 공 [Python]

Vermeil 2021. 4. 28. 21:54

www.acmicpc.net/problem/1396

 

1396번: 크루스칼의 공

첫째 줄에는 그래프의 정점의 개수 n과 간선의 개수 m이 주어진다. 그리고 두 번째 줄에서 m+1번째 줄까지는 a b c의 형태로 a와 b를 잇는 간선의 고유값이 c라는 의미이다. m+2번째 줄에는 알고 싶은

www.acmicpc.net

원래는 lca 공부하면서 풀려고 했는데, 누군가가 나보고 병렬 이분탐색 문제를 주면서 풀라고 하길래 이론만 강의로 듣고 다음날 까먹었다!

 

병렬 이분탐색에 대해서는 여기에 정말로 잘 나와있으니 모른다면 정독하고 오자.

 

열심히 구현했는데, 아직 완전히 내것이 된게 아니라 나중에 다시 한번 또 풀거다

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
import sys
input = sys.stdin.readline
 
MAX = 100001
 
def find(x):
    if x == p[x]: return x
    p[x] = find(p[x])
    return p[x]
 
def union(x, y):
    x = find(x)
    y = find(y)
    if x != y:
        p[x] = y
        cnt[y] += cnt[x]
 
n,m = map(int, input().split())
= []
for i in range(m):
    start,end,cost = map(int, input().split())
    g.append([cost, start, end])
 
g.sort(key=lambda x:x[0])
 
= int(input())
query = []
for i in range(q):
    start, end = map(int, input().split())
    query.append([start, end])
 
lo = [0 for _ in range(MAX)]
hi = [m+1 for _ in range(MAX)]
ans = [[0,0for _ in range(MAX)]
fl = True
while fl:
    # print(lo[:2],hi[:2])
    a = [[] for _ in range(MAX)]
    p = [i for i in range(MAX)]
    cnt = [1 for i in range(MAX)]
    fl = False
    for i in range(q):
        if lo[i]<hi[i]:
            a[(lo[i]+hi[i])//2].append(i)
 
    for i in range(1, m+1):
        cost = g[i-1][0]
        start = g[i-1][1]
        end = g[i-1][2]
        union(start, end)
 
        for j in a[i]:
            fl = True
            x = find(query[j][0])
            y = find(query[j][1])
            if x==y:
                hi[j] = i
                ans[j][0= cost
                ans[j][1= cnt[find(x)]
            else:
                lo[j] = i+1
 
for i in range(q):
    if lo[i] == m+1print(-1)
    elseprint(ans[i][0], ans[i][1])
cs