그래프에서 서로 연결된 세 정점의 차수 합의 최솟값 찾기
서로 친구인 a,b,c에 대하여 a의 친구 수 + b의 친구 수 + c의 친구 수가 최소가 되도록 만들고 싶다.
a의 친구 수에는 b,c는 제외해야한다.
마찬가지로 b,c의 친구 수에는 a,c, a,b는 제외해야한다.
a의 친구 수 + b의 친구 수 + c의 친구 수 - 6의 최솟값을 찾아야한다는 소리
친구 관계를 그래프로 만드는데 각 정점에 연결된 정점을 set()으로 만들어서 O(1)로 서로 친구인 정점을 찾도록 만들자
from sys import stdin
n,m = map(int,stdin.readline().split())
graph = [set() for _ in range(n+1)]
for _ in range(m):
a,b = map(int,stdin.readline().split())
graph[a].add(b)
graph[b].add(a)
정점 a를 1번부터 n번까지 순회해서, 서로 친구인 세 정점 a,b,c를 찾아야하므로
a에 연결된 정점 수가 2이상인 경우만 해당이 된다
for a in range(1,n+1):
if len(graph[a]) >= 2:
if len(graph[a]) >= 2를 안하면 시간이 100배 더 오래걸리더라
이거 하니까 시간이 100배 더 빨라짐..
아무튼
------------------------------------------------------------------------------------------------------------------------------------------
이 조건을 만족하는 정점 a에 대하여, a에 연결된 정점 graph[a]를 다시 순회해서 그들을 b로 하면
a,b는 친구가 된다
for a in range(1,n+1):
if len(graph[a]) >= 2:
for b in graph[a]:
마찬가지로 b의 정점과 연결된 정점들 graph[b]에서 순회하면 그 c는 일단 b랑은 친구고
a와도 친구여야 하므로, c in graph[a]가 만족해야한다
이걸 O(1)에 하기 위해 연결된 정점들을 set()으로 관리함
for a in range(1,n+1):
if len(graph[a]) >= 2:
for b in graph[a]:
for c in graph[b]:
if c in graph[a]:
이렇게 하면 서로가 친구인 3명 a,b,c를 찾았으니 len(graph[a]) + len(graph[b]) + len(graph[c]) - 6의 최솟값을 찾으면 된다
최솟값이 갱신이 안되면 그러한 세 친구 a,b,c를 찾을 수 없다는 뜻
조금 더 섬세한 테크닉으로
a를 1번부터 n번까지 순회하고 graph[a]에서 b를 순회하고 graph[b]에서 c를 순회해서
(a,b,c)를 찾는데
예를 들어 (1,3,5)를 찾았다고 해보자
a = 3이 되면 1번과 3번은 서로 친구이므로 (3,1,5)가 나오는데
3번 친구의 합 + 1번 친구의 합 + 5번 친구의 합은 당연히 1번 친구의 합 + 3번 친구의 합 + 5번 친구의 합과 같다
그러니까 a < b < c를 만족하는 a,b,c를 찾으면 중복 계산을 더 줄일 수 있다
from sys import stdin
n,m = map(int,stdin.readline().split())
graph = [set() for _ in range(n+1)]
for _ in range(m):
a,b = map(int,stdin.readline().split())
graph[a].add(b)
graph[b].add(a)
INF = 10**18
answer = INF
for a in range(1,n+1):
if len(graph[a]) >= 2:
for b in graph[a]:
if b > a:
for c in graph[b]:
if c > b and c in graph[a]:
v = len(graph[a]) + len(graph[b]) + len(graph[c]) - 6
if answer > v:
answer = v
if answer == INF:
print(-1)
else:
print(answer)
'알고리즘 > 브루트포스' 카테고리의 다른 글
탐색 범위를 줄여야하는 브루트포스 연습1 - 각 자릿수의 제곱합? (0) | 2024.10.24 |
---|---|
좌표들이 주어질때 좌표간 간격이 될 수 있는 모든 수를 찾는 방법 (0) | 2024.09.24 |
모든 집합의 합집합과 다르게 되는 일부를 골라 만든 최대 합집합 (0) | 2024.09.09 |
생각해서 브루트포스 탐색 범위를 줄여야하는 경우1 (장난감 강아지) (0) | 2024.02.03 |
잊을만하면 순열조합 연습하기 -치킨배달- (0) | 2022.10.30 |