일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Cloud Pub/Sub
- 다익스트라
- 수학
- ICPC
- 고속 푸리에 변환
- CI/CD
- 다이나믹 프로그래밍
- 백준 1753번
- REACT
- 데이터 분석
- 접미사 배열
- 이분탐색
- 펜윅 트리
- dp
- 삼성SW역량테스트
- 생활코딩
- Bit
- 그리디
- 삼성 SW 역량테스트
- 우선순위 큐
- BFS
- LCS
- r
- 시뮬레이션
- 컴퓨터 구조
- 종만북
- JavaScript
- jpa
- Cloud Run
- Air Table
- Today
- Total
코딩스토리
6강 - 그래프 본문
목차
- 그래프 추상 데이터 타입
- 그래프의 기본 연산
- 최소 비용 신장 트리
- 최단 경로와 이행적 폐쇄
- 작업 네트워크
1. 그래프 추상 데이터 타입
그래프는 이산수학에서도 배웠다시피 오일러의 퀸즈 버그 다리 문제에서 처음 사용되었다고 한다.
그래프의 정의 : 그래프는 두 개의 집합 V와 E로 구성된다. V는 정점(vertex), E는 간선(edge)로 이루어진 유한 집합이다.
임의의 그래프 G = (V, E)로 나타낼 수 있으며, 간선을 나타내는 정점의 쌍에 순서가 있거나 없음을 통해 무방향, 방향 그래프로 나눌 수 있다. 예를 들어 트리구조도 그래프라 할 수 있는데 이는 무 방향 그래프라 할 수 있다.
ex) (u,v) 는 무방향 그래프에서 표현, (v, u)와 같은 표현임.
<u,v>는 유방 향 그래프에서 표현, <v, u>와 다른 표현임
완전 그래프 - 모든 정점이 자신을 제외한 모든 정점과의 간선을 가지고 있는 그래프
무방향 그래프 - n개의 정점과 n(n-1)/2개의 간선을 가짐
유방향 그래프 - n개의 정점과 n(n-1) 개의 간선을 가짐
단순 경로 : 경로에서 처음과 마지막을 제외한 모든 정점들이 서로 다른 경로
연결 그래프 : 모든 정점 사이에 경로가 존재하는 그래프(한 정점에서 모든 정점과 연결되어 있지 않아도 됨 ex) tree )
연결 요소 : 최대 연결 그래프
강력 연결 : 방향 그래프에서 V(G)에 속한 서로 다른 두 정점 u,v의 모든 쌍에 대해서, u에서 v로, 또한 v에서 u로의 방향 경로가 존재하면 그 방향 그래프는 강력 연결되었다고 한다.
강력 요소 : 강력 연결된 최대 부분 그래프
그래프의 표현 방법
그래프는 인접 행렬, 인접 리스트로 표현이 가능하다.
인접 행렬로 표현 -> 임의의 두 정점 i, j 를 연결하는 간선이 존재하는지 바로 확인 가능
ex) 아래와 같이 정점 i, j에 대해 간선이 존재하면 1로, 존재하지 않으면 0으로 표현
0 | 1 | 2 | 3 | |
0 | 0 | 0 | 1 | 0 |
1 | 0 | 0 | 0 | 1 |
2 | 1 | 0 | 0 | 0 |
3 | 0 | 1 | 0 | 0 |
인접 리스트로 표현 -> 간선이 존재하면 체인으로 표현
역 인접 리스트 -> 인접 리스트가 진출 차수를 표현한다면 역 인접 리스트는 출입 차수를 표현하는 리스트이다.
2. 그래프의 기본 연산
깊이 우선 탐색 - DFS(Depth first search)
출발 정점을 방문 하고, 그 정점으로부터 간선이 있는 정점들 중 방문하지 않은 정점을 선택하여 방문, 이를 더 이상 방문할 정점이 없을 때까지 반복하고, 다시 되돌아와서 위 과정을 반복한다.
따라서 주로 stack을 사용하며 재귀함수로 표현된다.
넓이 우선 탐색 - BFS(Breadth first search)
출발 정점을 방문하고 그 정점과 간선이 있는 모든 노드들을 방문한다. 그 후 방문한 모든 노드들과 간선이 있는 모든 노드들을 방문한다. 이 과정을 더 이상 방문할 노드가 없을 때까지 반복한다.
따라서 주로 queue를 사용하여 표현된다.
간단히 정리하면 위와 같고 DFS와 BFS는 실제로 많이 구현해 봐야 익숙해 질 수 있는 것 같다.
이렇게 DFS, BFS를 통해 연결 요소를 구할 수 있다. (DFS, BFS는 연결된 모든 정점을 방문하는 알고리즘이기 때문)
신장 트리
신장 트리란 그래프의 모든 정점을 포함하고, 간선들이 그래프의 간선들로만 이루어진 트리를 말한다.
신장 트리는 DFS와 BFS 두 알고리즘 모두로 만들 수 있는데 둘은 차이가 있다.
직접 그려보며 이해해보자. 알고리즘을 따라가면 쉽게 구할 수 있다.
3. 최소 비용 신장 트리
최소 비용 신장 트리란 가중치를 갖는 그래프에서 최소의 비용을 갖는 신장 트리를 의미한다.
최소 비용 신장 트리를 구하는 알고리즘은 2가지 방법이 있다.
- Kruskal 알고리즘 : 가장 가중치가 적은 간선들만 연결 (사이클이 생기면 건너 뜀)
- Prim 알고리즘 : 첫 정점 부터 차례대로 가지고 있는 간선 중 가중치가 가장 적은 간선을 선택하여 연결
- Solin 알고리즘 : 모든 정점에서 가중치가 가장 적은 간선들만 연결 후 중복 제거, 반복
Prim 알고리즘은 각 단계에서 결정되는 간선들과 정점들은 트리 구조를 이루고 있음을 알 수 있다.
4. 최단 경로와 이행적 폐쇄
최단 경로 알고리즘 - Dijkstra Algorithm
먼저 이 알고리즘을 사용하려면 단일 시발점/일반적 가중치를 가진 그래프여야 한다.
첫 정점에서 시작 -> 정점에 존재하는 모든 간선의 가중치를 계산하여 표에 작성 (이때 아직 간선이 없어 가지 못하거나 방문하지 않은 정점은 거리를 무한대로 표현) -> 모든 정점 중 가중치가 가장 적은 정점을 다음 정점으로 선택 -> 정점에 존재하는 모든 간선의 가중치 계산하여 표에 작성 -> 모든 정점을 방문할 때까지 반복
말로 설명하려고 하니 살짝 어려운 것 같지만 실제로 표로 작성해보면 어렵지 않다.
코드로 나타내면 아래와 같다.
void MatrixWDigraph::ShortestPath(const int n, const inv v){
//dist[j] , 0<=j<n은 v에서 j까지의 최단 경로의 길이이다.
//간선의 길이는 length[i][j]로 주어진다.
for(int i=; i<n; i++){s[i]=false;dist[i]=length[v][i];} //초기화
s[v]=true;
dist[v]=0;
for(int i=0; i<n-2; i++){ //정점 v에서부터의 n-1 경로를 결정
int u = Choose (n); //Choose는 s[w]=false이고
//dist[u] 는 dist[u]가 미니멈이 되는 u를 반환
s[u]=true;
for(int w=0; w<n; w++){
if(!s[w]&&dist[u]+length[u][w]<dist[w])
dist[w]=dist[u]+length[u][w];
}
}
위의 알고리즘은 일반적인 가중치를 가졌을 경우에 최단 경로를 구하는 알고리즘이다.
만약 음의 가중치를 가지고 있는 그래프에서 최단 경로를 구하려면 어떻게 해야 할까?
음의 가중치를 가지고 있다면 많은 문제가 발생할 수 있다.
예를 들어 싸이클을 가지고 있는 그래프라면 경로가 -가 나올 수도 있다.
이러한 경우에 최단 경로를 구할 수 있는 알고리즘이 Bellman Ford 알고리즘이다.
Bellman Ford 알고리즘
이 알고리즘은 동적 프로그래밍(Dinamic Programming) 기법을 사용한다.
알고리즘의 핵심은 다음과 같다.
음의 가중치를 갖는 간선이 존재하기 때문에 동적 프로그래밍을 통해 모든 경로를 탐색해야 한다.
min(min(직접 가는 경우 , 정점 1개를 거쳐서 가는 경우), 정점 2개를 거쳐서 가는 경우)... 정점 n-1개를 거쳐서 가는 경우)
즉 계속해서 거쳐서 가는 정점의 개수를 늘려가며 기존의 최단 경로와 비교해 갱신해 나가는 알고리즘이다.
코드로 나타내 보면 아래와 같다.
dist_k[u] = min ( dist_k [u], min ( dist_k-1 [i] + length [i][u] )
이행적 폐쇄
이행적 폐쇄 행렬 - A+로 나타내며 i에서 j로의 경로의 길이가 >0 을 표현한 행렬이다.
반사 이행적 폐쇄 행렬 - A*로 나타내며 i에서 j로의 경로의 길이가 >=0 인 점들을 표현한 행렬이다.
이행적 폐쇄 행렬의 대각선(i==j) 부분이 모두 1로 채워지면 반사 이행적 폐쇄 행렬임을 쉽게 알 수 있다.
5. 작업 네트워크
AOV 네트워크 - 노드가 작업
- 정점 i로 부터 정점 j 로의 방향 경로 존재하면 정점 i는 정점 j의 선행자
- 간선 <i,j>가 존재하면 정점 i는 정점 j의 직속 선행자
부분 순서
- 이행적 - 관계 &에 대하여 i&j이고 j&k 이면 i&k이다.
- 비반사적 - 관계 &에 대하여 i&i가 성립하지 않는다.
부분 순서는 이행적이며 비반사적인 선행 관계이다.
위상 순서 : i, j에 대하여 네트워크에서 i가 j의 선행자이면, 그래프의 정점에서도 i가 j앞에 있는 선형 순서
AOE 네트워크 - 정점이 작업
임계 경로 : 시작 정점에서 종료 정점 가지의 최장 경로
임계 작업 : 임계 경로 상의 작업들
정점 중심 시간
e(i) = ee [k] -> 사건 k의 가장 이른 발생 시간
l(i) = le [k] - 작업 ai의 기간 -> 사건 l의 가장 늦은 발생시간
즉 ee와 le를 통해 e와 l을 구하고 e==l이면 임계 경로임을 알 수 있다.
'자료구조와 c++' 카테고리의 다른 글
5장 - 트리 (0) | 2020.06.07 |
---|---|
4강 - 연결리스트 (1) | 2020.06.03 |
3장 - 스택과 큐 (1) | 2020.05.29 |
2장 - 배열 (0) | 2020.05.27 |
1장 - 기본개념 (0) | 2020.05.26 |