문제


https://www.acmicpc.net/problem/2519


풀이


파이프 청소와 매우 유사하다.

추가된 것이라곤 각 학생별로 세 막대 중 하나만 제거할 수 있는 점이다.

이는 6개의 간선을 추가함으로써 해결된다.


코드


import sys
sys.setrecursionlimit(10 ** 5)


def ccw(x1, y1, x2, y2, x3, y3):
    return (x2 - x1) * (y3 - y2) - (x3 - x2) * (y2 - y1)


def intersect(x1, y1, x2, y2, x3, y3, x4, y4):
    res1 = ccw(x1, y1, x2, y2, x3, y3)
    res2 = ccw(x1, y1, x2, y2, x4, y4)
    res3 = ccw(x3, y3, x4, y4, x1, y1)
    res4 = ccw(x3, y3, x4, y4, x2, y2)

    return (res1 * res2 < 0) and (res3 * res4 < 0)


n = int(sys.stdin.readline())
stick = [tuple(map(int, sys.stdin.readline().split())) for _ in range(3 * n)]
graph = [[] for _ in range(6 * n + 1)]

for i in range(n):
    graph[3 * i + 1].append(-3 * i - 2)
    graph[3 * i + 1].append(-3 * i - 3)
    graph[3 * i + 2].append(-3 * i - 3)
    graph[3 * i + 2].append(-3 * i - 1)
    graph[3 * i + 3].append(-3 * i - 1)
    graph[3 * i + 3].append(-3 * i - 2)

for i in range(1, 3 * n + 1):
    for j in range(1, i):
        if intersect(*stick[i - 1], *stick[j - 1]):
            graph[-i].append(j)
            graph[-j].append(i)

stack = []
scc_num = 1
scc_idx = [0] * (6 * n + 1)
finish = [0] * (6 * n + 1)
visit = [0] * (6 * n + 1)
idx = 1


def dfs(cur):
    global idx, scc_num
    visit[cur] = idx
    low = idx
    idx += 1
    stack.append(cur)

    for nxt in graph[cur]:
        if not visit[nxt]:
            low = min(low, dfs(nxt))
        elif not finish[nxt]:
            low = min(low, visit[nxt])

    if low == visit[cur]:
        while stack:
            top = stack.pop()
            finish[top] = 1
            scc_idx[top] = scc_num
            if cur == top:
                break

        scc_num += 1

    return low


for i in range(1, 6 * n + 1):
    if not visit[i]:
        dfs(i)

res = [0] * (3 * n)
for i in range(1, 3 * n + 1):
    if scc_idx[i] == scc_idx[-i]:
        print(-1)
        break
    if scc_idx[i] < scc_idx[-i]:
        res[i - 1] = 1
else:
    print(res.count(1))
    for i in range(3 * n):
        if res[i]:
            print(i + 1, end=' ')

Leave a comment