밍경송의 E.B

<11> 그래프2 본문

CSE/자료구조&알고리즘

<11> 그래프2

m_gyxxmi 2023. 12. 14. 01:47

이 글은 시험이 1일 어쩌고정도 남은 사람이 내용 정리를 위해 적는 글입니다.
*[C언어로 쉽게 풀어쓴 자료구조]  책과 숙영리 교수님의 강의를 참고하여 작성하였음을 밝힙니다.🦭
 
 
 

신장트리 

: 그래프 내의 모든 정점을 포함하는 트리 (|V|-1개의 |E|를 가짐)

 
 
 

🦭 MST(최소비용신장트리) 🦭

: 그래프의 모든 정점들을 가장 적은 수의 간선과 비용(가중치 그래프의 경우) 으로 연결 -> 전체적으로 비용 감소 목적

*if weight가 동일한 간선이 있다면, 여러 MST가 나올 수도 있음!
 

더보기

그래프 G = (V,E)의 MST G' = (V',E')의 조건

1) V = V'

2) E'은 E의 부분 집합, |E'| = |V| -1 (no cycle in G') 

3) Sum(weight of edges in E') is minimum

그래 MST도 트리지 그래 그러면 cycle이 없겠구나 그래그래
 


 

 

🦭1 Kruskal's MST 알고리즘 

*ecounter : 현재 MST에 포함된 edge의 개수 (가 node -1 개가 될 때까지 while문을 돌아라)
*k :  현재 (weight이 작은 순서부터) 검사한 edge의 수
 
Ex)
 

 
=> {ek}를 추가하면 cycle이 생기지 않는다는 것을 어떻게 확인할 수 있을까?
 
 

"UNION-FIND 연산=Disjoint-set algorithm"

 
 
[알고리즘] 
내가 연결하려는 두 노드가 같은 집합에 있는지 확인하고, 없으면 연결하는 !

 
⚠️ 4번째 줄에 parent[root1] = root2;
: 노드 a의 루트인 노드의 부모를 노드 b의 루트 노드로 하겠다 ! 
그러니까 만약 null graph 상태라면 b→a  요렇게 연결되는 거임 순서에 주의하쟈
UNION(a,b) =  b→a  .. 이렇게 됩니다 
그렇다보니 UNION(b,a)랑 (a,b)는 다르겠
 


 

더보기

UNION-FIND (X,Y) 연산 잘하는 법 - 만약 연산이 줄줄이 나올 때라면!

1) X의 루트를 찾자 (-1인지 다른 노드 값인지 암튼 찾자)

2) Y의 루트를 찾자 

3) 같지 않다면 P[1)] =2) 노드 연결하기  (간선 생성)

4) 1)의 값을 2)의 값으로 바꿔주기

처음 풀 때 헷갈렸던 거는..  null, UNION(H,C) , UNION(H,G) 요렇게 순차적으로 나올 때 
첫 번째 연사에 의해서 C→H 이렇게 연결되고, 뒤에 연산을 할 때는 P[C] = G  니까 G →C→H 요렇게 되는 거를 이해 못 해따!
 

Q. X와 Y의 대표(루트)노드가 같은가 ? = ((FIND(X)==(FIND(Y))? = X와 Y가 같은 그룹에 속했는가? = X와 Y 사이에 간선을 추가하면 cycle이 생기는가?

 


U-F를 이용한 kruskal 프로그램

MST에 포함되는 간선의 수가 정점 수 -1가 될 떄까지!니까 요게 필요
while문에 g-&gt;nv-1

 
 


 

🦭2 Prim's MST 알고리즘 

: 시작 정점(아무 노드나)부터 출발하여 신장트리 집합을 단계적으로 확장 - 신장트리 집합에 인접한 정점 중에서 최저 간선으로 연결된 정점을 선택하여 집합에 추가 
*Kruskal은 weight이 적은 간선부터 골랐는데 얘는 시작노드를 중심으로 퍼져나가는 느낌스
 
 
Ex)

인접정점에 g가 없으면 g의 dist는 INF

 

Q. 노드 b부터 시작할 때 3번째로 추가되는 간선의 w는?
Q. g의 dist가 몇 번이나 업데이트 되는가?
 

 
[알고리즘]

*dist[v]: v가 현 MST와 직접 연결된 간선의 weight
 

*시작정점이 무엇인지에 따라 MST 집합에 간선이 추가되는 순서는 달라질 수 있지만, 최종적으로 얻어지는 MST의 구조는 달라지지 않는다악!

=> Uniqueness of MST 
: G의 모든 간선의 weight이 다르다면, MST는 unique하다.
 
 

* if (!selected[v] && g->weight[u][v] < distance[v]) 
: 아직 MST에 포함되지 않은 노드이면서, 이전 MST와의 거리(dist[v])보다 직전에 MST에 포함된 노드(u)를 통한 간선의 거리(g->weight[u][v])가 더 가깝다면!  distance[v]를 업데이트해라~~
 
*Prim은 시작정점과 연결된 그래프 안에서만 작동!!!! 
ㄴ 생각해보면 Kruskal은 그냥 w에 따라 진행해나가는 거니까, disconnected 된 그래프여도 동작 가능한데, 얘는 인접정점 기준으로 뻗어나가니까 ...융 그럴 수 있네
 

주어진 G의 weight이 모두 distinct라면 Kruskal로 얻은 결과나 Prim으로 얻은 결과나 동일함!
(순서는 다를 수도 같을 수도 있음엽)

 


정리🤔

그래 그렇군나!

Prim에서 하나의 노드를 여러 번 방문한다는 소리는 dist[x]를 계속 계속 업데이트한다는 그런 뜻!
그래서 희박한 그래프는 kruskal이 굳, 밀집된 그래프는 prim이 굳이랍니다!
 
 
 


 
 
.. 왤케 많쥐..
 

🐈 Shortest Path (최단경로) 🐈

: 경로란.. 시작정점과 종료정점이 제시된 것. 
최단 경로란? 정점u와 정점 v를 연결하는 경로 중에 간선들의 가중치 합이 최소! 가 되는 경로
*MST랑 관점이 아예 다름..이 포인트
 
⚠️가중치 인접행렬을 갱신해가며 사용함. *직접가는 간선이 없는 경우 : 무한으로 표

 
 


 
 

🐈 Dijkstra 알고리즘🐈

: 하나의 시작 정점(기준)에서 다른 모든 정점(|V|-1) 까지의 최단 경로를 계산하는 알고리즘
 
*집합 S: 시작 정점으로부터 최단 경로가 이미 발견된 정점들의 집합
한 노드가 S에 들어갔다? = 시작 정점으로부터 그 노드까지의 최단 경로가 밝혀졌다! (추리게임같네....
*distance[] : 최단 경로가 알려진 정점들만 이용한 다른 정점들까지의 최다 경로 길이. (계속 바뀜 주의)
 

 

⚠️ round를 한 번 돌 때마다, 하나의 정점으로의 shortest path가 구해짐
증명은 그림으로 대체...

 
 

*여기서 중요한 것은 이 증명이 성립하려면 간선의 가중치는 0보다 작으면 안된다는 것!

그럼 합이 최단 경로보다 작아질 수도 있기 때문에... ! 0까지는 가능함
 
 
[알고리즘]

 
EX)

V=7, 6개의 shortest path 찾기!
뒤로 갈 수록 표 그리기 귀찮..았어요

⚠️헷갈렸던 거는..  s= {0,4,1}일 때, s 자체를 한 뭉텅이?로 보고 음 거기서 제일 짧은 간선은 2로 가는 거니까 2인가보다~ 했는데 이거는 Prim 알고리즘이었던 것.. ㅠ 몬가 시작 정점이 있다는 거 땜에 둘이 잠깐 헷갈림
그러니까,, Dijkstra 이거는 s에 없으면서, 그때 그때 시작정점으로부터 제일 가까운 애를 고르는 것임!
그림에서 2번째 표에서 6이 가중치 8로, 선택되지 않은 애들 중에 제일 가까운 애니까 걔를 골라야!>.! 했다 
표를 무족건 그리자 무조건 잘.

 
[알고리즘]

맨 밑에 for문 정도는 적을 줄 알면 좋겠다

 
min-heap을 사용하면 O(|V| *log|V|) 안에 해결이 가능하다....고 한다.
 


 
 

🐈 Floyd 알고리즘🐈

: 모든 정점에서 다른 모든 정점까지의 최단 경로를 계산하는 알고리즘
[알고리즘]

2차원 배열A를 이용하여 3중 반복을 하는 어쩌고 저쩌고

* 음의 가중치를 허용
 
다른 내용은 오히려 이해를 어렵게 만드는...데 요걸 보면 좀 이해가 간다

*이미 안의 for문 안에서 i에서 k로의 shortest path에 대한 정점 비교가 된 상태이기 때문에 바로 k를 거치냐 마냐로 들어갈 수 있는 것

 
EX)

: A^0[i][j] = min(A^-1[i][j], A^-1[i][0] + A^-1[0][j])
 

: A^1[i][j] = min(A^0[i][j], A^0[i][1] + A^0[1][j])

 
이거를 모든 정점에 대해서 다 해보면 완-성! 
안 하고 싶다...
 


 

🐲위상정렬(topological) 🐲

: 방향 그래프이면서 사이클이 없는 G에서, 정점들의 선행순서를 위배하지 않으면서 모든 정점을 나열
 
⚠️ 여기서 알아야할 것은 선행 노드가 존재한다 = 그 정점으로의 in_degree 값이 존재한다
-> 따라서? 시작 정점을 in-degree가 0인 노드로 하는 것이 좋다!
 

 
 
 
[알고리즘]

DAG가 아니면 위상 정렬은 아예 불가능쓰

 
[EX]

 
 
*코드에서는 스택을 이용했는데, 큐를 이용해도 된다고 합용

간선이 있으면 in_degree[] ++

 

*위의 예제대로 보면, 일단 in_degree가 0인 정점이 1이랑 0이니까 얘네가 스택에 들어가겠조 (요 순서는 아마 정해야할듯)
그 다음에 1이 pop되고, 1이 pop됨으로써 in_degree가 0이 되는 정점을 push해주고 또 pop하고 요런 식으로 하는 것!

 
stack의 상태 변화나 pop되는 순서 같은 거 물어보기 굳.>!!!!!!!
 
 
끝.

'CSE > 자료구조&알고리즘' 카테고리의 다른 글

<12> 정렬  (0) 2023.12.14
<10> 그래프 1  (0) 2023.12.12
<7> 원형 연결리스트, 이중 연결리스트  (1) 2023.10.26
<6> 단일 연결리스트  (1) 2023.10.26
<5> 큐(Queue)  (0) 2023.10.26