690 likes | 1.31k Views
자료구조. 제 6 장 그래프. 6.1 그래프 추상 데이타 타입. 6.1 그래프 추상 데이타 타입. ▶ 개요 - Koenigsberg 다리 문제 - 차수 (degree) : 정점에 연결된 간선의 수 - 오일러 행로 (Eulerian walk) 그림 6.1: (a) Koenigsberg 의 Pregal 강의 일부 (b) Euler 의 그래프. 6.1 그래프 추상 데이타 타입. ▶ 정의 - 그래프 G : 2 개의 집합 V 와 E 로 구성
E N D
자료구조 제 6 장 그래프
6.1 그래프 추상 데이타 타입 • ▶ 개요 • - Koenigsberg 다리 문제 • - 차수(degree) : 정점에 연결된 간선의 수 • - 오일러 행로(Eulerian walk) • 그림 6.1: (a) Koenigsberg의 Pregal강의 일부 • (b) Euler의 그래프
6.1 그래프 추상 데이타 타입 • ▶ 정의 • - 그래프 G : 2개의 집합 V와 E로 구성 • •V : 공집합이 아닌 정점(vertices)의 유한집합 • •G : 간선(edges)의 집합 • •표기 : G=(V,E) • - 무방향그래프(undirected graph) • •간선을 나타내는 정점의 쌍에 순서 없음 • - 방향 그래프(directed graph) • •간선을 나타내는 정점의 쌍에 순서 있음 • •간선 : 방향을 가지는 정점의 쌍 <u,v>로 표시 • (u는 꼬리(tail), v는 머리(head)) • 그림 6.2: 세개의 예제 그래프
6.1 그래프 추상 데이타 타입 • - 그래프의 제한 사항 • (1) 자기 간선(self edge) 또는 자기 루프(self loop) 없음 • (2) 동일 간선의 중복 없음 • (다중그래프(multigraph)는 이 제한이 없음) • 그림 6.3: 그래프 형태 구조의 예 • - 완전 그래프(complete graph) • : n개의 정점과 n(n-1)/2개의 간선을 가진 그래프 - (u,v)가 E(G)의 한 간선이라면 • u와 v는 인접(adjacent)한다 • •간선 (u,v)는 정점 u와 v에 부속(incident)된다 • - 그래프 G의 부분그래프(subgraph) • : V(G')⊆V(G)이고 E(G')⊆E(G)인 그래프 G'
6.1 그래프 추상 데이타 타입 • 정점 u로부터 정점 v까지의 경로(path) : 그래프 G에서 (u,i1), (i1,i2), ..., (ik,v)를 E(G)에 속한 간선들이라 할 때, 정점열 u, i1, i2, ..., ik, v를 말함 • - 경로의 길이(length) : 경로상에 있는 간선의 수 • - 단순 경로(simple path) • : 경로상에서 처음과 마지막을 제외한 모든 정점들이 • 서로 다름 • - 단순 방향 경로(simple directed path) • - 사이클(cycle) • : 처음과 마지막 정점이 같은 단순 경로 • 그림 6.4: 부분그래프
6.1 그래프 추상 데이타 타입 • - 연결요소(connected component) • :최대연결부분그래프(maximalconnected subgraph) • - 강력 연결(strongly connected) • : 방향그래프에서 V(G)에 속한 서로 다른 두 정점 u, v • 의 모든 쌍에 대해서, u에서 v로, 또한 v에서 u로의 • 방향 경로(directed path)가 존재 • - 강력 연결요소(strongly connected component) • : 강하게 연결된 최대 부분그래프 • 그림 6.5: 두 개의 연결요소를 갖는 그래프
6.1 그래프 추상 데이타 타입 • 그림 6.6: G3의 강력 연결요소 • - 차수(degree) : 정점에 부속한 간선들의 수 • - 진입차수(in-degree) • : 임의의 정점 v가 머리가 되는 간선들의 수 • - 진출차수(out-degree) • : v가 꼬리가 되는 간선들의 수 • - 간선의 수 • (n개의 정점, e개의 간선, 정점 i의 차수를 di) • - 다이그래프(digraph) : 방향 그래프
6.1 그래프 추상 데이타 타입 • ----------------------------------------- • classGraph • { • // objects:공집합이 아닌 정점의 집합과 무방향 간선의 집 • //합으로각 간선은 정점의 쌍임. • public: • Graph(); • // 하나의 공백 그래프를 생성 • voidInsertVertex(Vertex v); • // v를 그래프에 삽입; v는 부속한 간선을 갖지 않음 • voidInsertEdge(Vertex u, Vertex v); • // 간선 (u,v)를 그래프에 삽입 • voidDeleteVertex(Vertex v); • // v와 v에 부속된 모든 간선들을 삭제 • voidDeleteEdge(Vertex u, Vertex v); • // 간선 (u,v)를 그래프에서 삭제 • Boolean IsEmpty(graph); • // if그래프에 정점이 없음 returnTRUE (1); • // else returnFALSE (0); • List<Vertex> Adjacent(Vertex v); • // v에 인접한 모든 정점들의 리스트를 반환 • }; • ----------------------------------------- • ADT6.1: 그래프 추상 데이타 타입
6.1 그래프 추상 데이타 타입 • ▶ 그래프 표현법 • - 인접행렬 (Adjacency Matrix) • •G=(V,E)는 정점의 수가 n(n≥1)인 그래프 • •인접행렬 : n×n의 2차원 배열 • •간선 (vi, vj) E(G) A[i][j]=1 • •간선 (vi, vj) E(G) A[i][j]=0 • •필요 공간 : n2비트 • 그림 6.7: 인접행렬 • •무방향그래프 • : 어떤 정점 i의 차수는 그 행의 합 • •방향그래프 • : 행의 합은 진출차수, 열의 합은 진입차수 • •인접행렬의 수행 시간 : 최소한 O(n2) • •희소 그래프(sparse graph) : O(e+n)
6.1 그래프 추상 데이타 타입 • - 인접리스트 (Adjacency Lists) • •인접행렬의 n행들을 n개의 연결리스트로 표현 • •data와 link 필드 • •C++ 선언문 • class Graph • { • private: • List<int> *HeadNodes; • int n; • public: • Graph(const int vertices = 0) : n(vertices) • { HeadNodes = new List<int>[n]; }; • }; • •n개의 정점, e개의 간선의 무방향그래프 • : n개의 헤드노드, 2e개의 리스트 노드가 필요 • •방향그래프 : e개의 리스트 노드 • •역인접리스트(inverse adjacency lists) • : 리스트가 표현하는 정점에 인접한 각 정점에 대해 • 하나의 노드를 둠
6.1 그래프 추상 데이타 타입 • 그림 6.8: 인접리스트
6.1 그래프 추상 데이타 타입 • 그림 6.9: 그래프 G4의 순차적인 표현 • 그림 6.10: G3(그림 6.2(c))의 역인접리스트
6.1 그래프 추상 데이타 타입 • 그림 6.11: 그림 6.2(c)의 그래프 G3의 직교 리스트 표현
6.1 그래프 추상 데이타 타입 • - 인접다중리스트 (Adjacency Multilists) • •간선 (u,v)는 두 개의 엔트리로 표현 • : u를 위한 리스트, v를 위한 리스트에 나타남 • •새로운 노드 구조 • •C++ 선언문 • enumBoolean FALSE,TRUE; • class Graph; // 전방 선언 • class GraphEdge { • friend Graph; • private: • Boolean m; int vertex1, vertex2; GraphEdge*path1, *path2; • }; • typedefGraphEdge*EdgePtr; • class Graph { • private: • EdgePtr*HeadNodes;int n; • public: • Graph(constint); • }; // 헤드 노드 배열을 설정 • Graph::Graph(constint vertices = 0) : n(vertices){ • HeadNodes= new EdgePtr[n]; • for (int i=0; i<n; i++) HeadNodes[i]=0; • }
6.1 그래프 추상 데이타 타입 • 그림 6.12: 그림 6.2(a)의 G1에 대한 인접다중리스트 • - 가중치 간선 (Weighted Edges) • • 그래프의 간선에 가중치(weights) 부여 • • 인접행렬 : 항 A[i][j]에 가중치 정보 저장 • • 인접리스트 : 노드 구조에 weight 필드를 추가 • • 네트워크(network) : 가중치 간선을 가진 그래프
6.2 기본적인 그래프 연산 • ▶ 깊이 우선 탐색 • - 깊이 우선 탐색(DFS; Depth First Search) • ⑴ 출발 정점 v를 방문 • ⑵ v에 인접하고 방문하지 않은 한 정점 w를 선택 • ⑶ w를 시작점으로 다시 깊이 우선 탐색 시작 • ⑷ 모든 인접 정점을 방문한 정점 u에 도달하면, 최근에 방문한 정점 중 아직 방문을 안한 정점 w와 인접하고 있는 정점으로 되돌아감 • ⑸ 정점 w로부터 다시 깊이 우선 탐색 시작 • ⑹ 방문이 된 정점들로부터 방문이 안된 정점으로 더 이상 갈 수 없을 때 종료
6.2 기본적인 그래프 연산 • ----------------------------------------- • voidGraph::DFS() // 드라이버 • { • visited = newBoolean[n]; • // visited를 Graph의 Boolean* 데이타 멤버로 선언. • for(inti=0; i<n; i++) visited[i] = FALSE; • // 초기에는 방문된 정점이 없음 • DFS(0); // 정점 0에서 탐색을 시작 • delete[] visited; • } • voidGraph::DFS(constintv) // 실제 탐색 수행 • // 정점 v에서 도달 가능하면서 아직 방문되지 않은 모든 • //정점들을 방문 • { • visited[v] = TRUE; • for(v에 인접한 각 정점 w에 대해) • // 실제 코드는 그래프 표현 방법에 좌우됨 • if(!visited[w]) DFS(w); • } • ----------------------------------------- • 프로그램 6.1: 깊이 우선 탐색
6.2 기본적인 그래프 연산 • - 예제 6.1 • •0, 1, 3, 7, 4, 5, 2, 6 순으로 방문 • 그림 6.16: 그래프 G와 그 인접리스트 • - DFS의 분석 • •탐색을 끝내는 시간 O(e) • •v에 인접한 모든 정점들을 찾는데 O(n)의 시간 • •총 시간은 O(n2)
6.2 기본적인 그래프 연산 • ▶ 너비 우선 탐색 • - 너비 우선 탐색(BFS; Breath First Search) • ⑴ 시작 정점 v를 방문 • ⑵ v에 인접한 모든 정점들을 방문 • ⑶ 새롭게 방문한 정점들에 인접하면서 아직 방문하지 못한 정점들을 방문 • - 예제 6.2 • • 0, 1, 2, 3, 4, 5, 6, 7 순으로 방문
6.2 기본적인 그래프 연산 • ----------------------------------------- • voidGraph::BFS(intv) • // 정점 v에서 시작하여 너비 우선 탐색을 수행.v 방문시 • //visited[i]는 TRUE가 됨. 이 알고리즘은 큐를 사용함 • { • visited = newBoolean[n]; • // visited를 Graph의 Boolean* 데이타 멤버로 선언. • for(inti=0; i<n; i++) visited[i] = FALSE; • // 초기에는 방문한 정점이 없음 • visited[v] = TRUE; • Queue<int> q; // q는 큐임 • q.Insert(v); // 정점을 큐에 삽입 • while(!q.IsEmpty()) { • v = *q.Delete(v); // 정점 v를 큐에서 삭제 • for(v에 인접한 모든 정점 w에 대해) • // 실제 코드는 그래프 표현 방법에 좌우됨 • if(!visited[w]) { • q.Insert(w); • visited[w] = TRUE; • } • }// while루프의 끝 • delete[] visited; • } • ----------------------------------------- • 프로그램 6.2: 너비 우선 탐색
6.2 기본적인 그래프 연산 • - BFS의 분석 • •전체 시간 O(n2) • •인접 리스트 표현 : 전체 비용 O(e)
6.2 기본적인 그래프 연산 • ▶ 연결요소 • - 연결요소(connected component) • : 방문하지 않은 정점 v에 대해 DFS(v) 또는 BFS(v)를 반복 호출로 구함 • ----------------------------------------- • voidGraph::Components() { • // 그래프의 연결요소들을 결정. visited는 Graph의 • // Boolean* 데이타 멤버로 선언되는 것으로 가정. • visited = newBoolean[n]; • for(inti=0; i<n; i++) visited[i] = FALSE; • for(i=0; i<n; i++) • if(!visited[i]) { • DFS(i); // 하나의 요소를 발견 • OutputNewComponent(); • } • delete[] visited; • } • ----------------------------------------- • 프로그램 6.3: 연결요소의 결정 • - Components의 분석 • •인접리스트로 표현 • : 모든 연결요소들 생성 시간은 O(n+e) • •인접행렬로 표현 : O(n2)
6.2 기본적인 그래프 연산 • ▶ 신장트리 • - 신장트리(spanning tree) : G의 간선들로만 구성되고 G의 모든 정점들이 포함된 트리 • •깊이우선 신장트리(depth first spanning tree) • •너비우선 신장트리(breath first spanning tree) • 그림 6.17: 완전 그래프와 이 그래프의 세 신장트리 • 그림 6.18: 그림 6.16의 그래프에 대한 깊이우선 및 • 너비우선 신장트리
6.2 기본적인 그래프 연산 • - 예제 6.3 [회로 등식의 생성] • ⑴ 전기 네트워크에 대한 신장트리 구함 • ⑵ 비트리 간선을 신장트리에 한번에 하나씩 도입 • ⑶ Kirchoff의 제 2 법칙 이용하여 회로 등식 얻음 • -신장트리는G의최소부분그래프(minimal subgraph) G'로서 V(G') = V(G)이고 G'는 연결되어 있음 • - 신장트리는 n-1개의 간선 가짐
6.2 기본적인 그래프 연산 • ▶ 이중결합요소 • - 단절점(articulation point) • : 그래프 G의 정점들중 이 정점과 이 정점에 부속한 모든 간선들 삭제시, 최소한 두개의 연결요소를 갖는 그래프 G'가 되게 하는 정점 v • 그림 6.19: 연결 그래프와 이중결합요소들 • - 이중결합그래프(biconnected graph) • : 단절점이 없는 연결 그래프 • - 이중결합요소(biconnected component) • : 최대이중결합부분그래프(maximal biconnected subgraph) H
6.2 기본적인 그래프 연산 • 그림 6.20: 그림 6.19(a)의 깊이우선 신장트리 • - 백 간선(back edge) : u가 v의 조상이거나 v가 u의 조상인 비트리 간선 (u,v) • - 교차 간선(cross edge) : 백 간선이 아닌 비트리 간선 • - low(w) : w의 후손들과 많아야 하나의 백 간선으로 된 경로를 이용해 w로부터 도달할 수 있는 가장 적은 깊이우선번호 • low(w) = mindfn(w), minlow(x) | x는 w의 자식, • mindfn(x) | (w,x)는 백 간선
6.2 기본적인 그래프 연산 • 그림 6.21: 그림 6.20(b)의 신장 트리에 대한 dfn값과 low값
6.2 기본적인 그래프 연산 • ----------------------------------------- • voidGraph::DfnLow(constintx) { // 정점 x에서 DFS를 시작 • num = 1; // num는 classGraph의 int데이타 멤버 • dfn= new int[n]; // dfn은 classGraph에 int*로 선언 • low = new int[n]; // low는 classGraph에 int*로 선언 • for(inti=0; i<n; i++) dfn[i] = low[i] = 0; • DfnLow(x,-1); // 정점 x에서 시작 • delete[] dfn; • delete[] low; • } • voidGraph::DfnLow(constintu, constintv) { • // 정점 u에서 출발하여 깊이우선 탐색을 수행하면서 dfn과 • // low를 계산. • // v는 생성된 신장 트리에서 u의 부모 (존재하는 경우) • dfn[u] = low[u] = num++; • for(u로부터 인접한 각 정점 w에 대해) • // 실제 코드는 그래프 표현 방법에 좌우됨 • if(dfn[w]==0) { // w가 아직 방문하지 않은 정점이면 • DfnLow(w,u); • low[u] = min2(low[u],low[w]); • } • else if(w!=v) low[u] = min2(low[u],dfn[w]); // 백 간선 • } • ----------------------------------------- • 프로그램 6.4: dfn과 low의 계산
6.3 최소비용 신장트리 • - 최소비용 신장트리(minimum cost spanning tree) • : 최저의 비용을 갖는 신장트리 • - Kruskal, Prim, Sollin알고리즘 • - 갈망법(greedy method) • ⑴ 최적의 해를 단계별로 구한다 • ⑵ 각 단계에서는 몇개의 판단 기준에 따라 최상의 결정을 내린다 • ⑶ 한번 내려진 결정은 뒤에 번복이 불가능하므로 각각의 결정이 가능한 해를 도출해낼 수 있는 지 확인 • - 신장트리의 제한 조건 • (1) 그래프내에 있는 간선들만을 사용 • (2) 정확하게 n-1개의 간선만을 사용 • (3) 사이클을 생성하는 간선을 사용 금지
6.3 최소비용 신장트리 • ▶ Kruskal알고리즘 • - 알고리즘 • •한번에 하나씩 T에 간선을 추가해가면서 최소비용 신장트리 T를 구축 • •T에 포함될 간선을 비용의 크기순으로 선택 • •이미 T에 포함된 간선들과 사이클을 형성하지 않는 간선만을 T에 추가
6.3 최소비용 신장트리 • -예제 6.4 • 그림 6.22: Kruskal알고리즘의 각 단계
6.3 최소비용 신장트리 • ----------------------------------------- • 1 T = Ø • 2 while((T가 n-1개 미만의 간선을 포함) && (E가 공백이 아님)) { • 3 E에서 최소 비용 간선 (v,w) 선택; • 4 E에서 (v,w)를 삭제; • 5 if((v,w)가 T에서 사이클을 형성하지 않음) • T에 (v,w)를 추가; • 6 else(v,w)를 거부; • 7 } • 8 if(T가 n-1개 미만의 간선을 포함) • cout<< "신장 트리 없음" << endl; • ----------------------------------------- • 프로그램 6.6: Kruskal알고리즘 • - 정리 6.1 • •G를 무방향 연결 그래프라 하자. Kruskal알고리즘은 • 최소비용 신장트리를 생성한다.
6.3 최소비용 신장트리 • ▶ Prim 알고리즘 • - 알고리즘 • •한번에 한 간선씩 최소비용 신장트리를 구축 • •각 단계에서 선택된 간선의 집합은 트리 • •하나의 정점으로 된 트리 T에서 시작 • •최소 비용 간선 (u,v)를 구해 T ∪ {(u,v)}이 트리가 되면 T에 추가 • •T에 n-1개의 간선이 포함될 때까지 간선의 추가 단계를 반복 • •추가된 간선이 사이클을 형성하지 않도록 각 단계에서 간선 (u,v)를 선택할 때 u 또는 v중 오직 하나만 T에 속한 것을 고른다. • ----------------------------------------- • // G가 최소한 하나의 정점을 가진다고 가정. • TV = {0}; // 정점 0으로 시작. 간선은 비어있음. • for(T= Ø ; T의 간선수가 n-1보다 적음; (u,v)를 T에 추가) { • u ∈ TV이고 v TV인 최소 비용 간선을 (u,v)라 함; • if(그런 간선이 없음) break; • v를 TV에 추가; • } • if(T의 간선수가 n-1보다 적음) • cout<< "신장트리 없음" << endl; • ----------------------------------------- • 프로그램 6.7: Prim 알고리즘
6.3 최소비용 신장트리 • 그림 6.23: Prim 알고리즘의 단계들
6.3 최소비용 신장트리 • ▶ Sollin알고리즘 • - 알고리즘 • •각 단계에서 여러개의 간선을 선택 • •각 단계에서는 포리스트에 있는 각 트리에 대해 하나의 간선을 선택 • •이 간선은 오직 하나의 정점만 그 트리에 속한 최소 비용 간선 • •선택된 간선은 구축중인 신장트리에 추가 • •오직 하나의 트리만이 존재 or 더 이상 선택할 간선이 없을 때 종료 • 그림 6.24: Sollin알고리즘의 단계들
6.4 최단경로와 이행적 폐쇄 • ▶ 단일 시발점/모든 종점: 양수 간선 비용 • - 문제 : 시발 정점 v에서부터 G의 모든 다른 정점까지의 최단경로를 구하는 것 • 그림 6.25: 그래프와 정점 0에서 모든 종점까지의 최단경로
6.4 최단경로와 이행적 폐쇄 • - 알 수 있는 사실들 • •정점 v를 포함하여 이미 최단 경로가 발견된 정점의 집합을 S • •S에 속하지 않은 w에 대해서 dist[w]를 v에서 시작하여 S에 있는 정점만을 거쳐 w까지의 최단경로의 길이 • (1) 만일 다음으로 짧은 최단경로가 정점 u까지의 경로라면 v에서 u로의 경로는 오직 S에 속한 정점들만을 통하게 된다. • (2) 다음에 생성되는 경로의 종점은 S에 없는 정점들중에서 최소의 거리 dist[u]를 가진 정점 u가 되어야 한다. • (3) 일단 (2)에서 선택된 정점 u는 S의 원소가 된다. v에서 u로의 최단 경로는 (2)의 선택 과정을 통해 얻어진다. 이때, v에서 시작하여 S에 있는 정점만을 통해 현재 S에 속하지 않은 w까지의 최단경로의 길이는 감소될 수 있다. • - ShortestPath알고리즘
6.4 최단경로와 이행적 폐쇄 • - 클래스 정의 • class Graph • { • private: • int length[nmax][nmax]; • int dist[nmax]; • Boolean s[nmax]; • public: • void ShortestPath(constint, constint); • int choose(constint); • };
6.4 최단경로와 이행적 폐쇄 • ----------------------------------------- • 1 voidGraph::ShortestPath(constintn, constintv) • 2 // dist[j],0≤j<n는 n개의 정점을 가진 방향 그래프 G에서 • //정점 v로부터 정점 j까지 • 3 // 의 최단 경로 길이로 설정됨. 간선의 길이는 length[j][j] • //로 주어짐. • 4 { • 5 for(inti=0; i<n; i++) • { s[i] = FALSE; dist[i] = length[v][i]; } // 초기화 • 6 s[v] = TRUE; • 7 dist[v] = 0; • 8 for(i=0; i<n-2; i++) { // 정점 v로부터 n-1개 경로를 결정 • 9 intu = choose(n); • // choose는 dist[u] = minimum dist[w]인 u를 반환 • 10 // (여기서 s[w]=FALSE) • 11 s[u] = TRUE; • 12 for(intw=0; w<n; w++) • 13 if(!s[w]) • 14 if(dist[u] + length[u][w] < dist[w]) • 15 dist[w] = dist[u] + length[u][w]; • 16 } // for(i=0; ...)의 끝 • 17 } • ----------------------------------------- • 프로그램 6.8: 최단경로의 결정
6.4 최단경로와 이행적 폐쇄 • - ShortestPath의 분석: • n개의 정점을 가진 그래프에 대한 수행시간은 O(n2) • - 예제 6.5 • 그림 6.26: 예제 6.5에 대한 방향그래프
6.4 최단경로와 이행적 폐쇄 • 그림 6.27: 그림 6.26의 방향그래프에 대한 ShortestPath의 작동
6.4 최단경로와 이행적 폐쇄 • ▶ 단일 시발점/모든 종점: 일반적인 가중치 • - 음수 길이 사이클이 존재할 경우 최단 길이 경로가 존재하지 않는다. • 그림 6.28: 음의 길이 간선을 가진 방향 그래프 • 그림 6.29: 음의 길이 사이클을 가진 방향 그래프 • - 동적 프로그래밍 방법 • : 모든 u에 대해 distn-1[u]를 구함 • distk[u] = min{distk-1[u], min{distk-1[i] + length[i][u]}}
6.4 최단경로와 이행적 폐쇄 • - 예제 6.6 • 그림 6.30: 음의 길이 간선을 갖는 최단 경로
6.4 최단경로와 이행적 폐쇄 • - Bellman과 Ford 알고리즘 • ----------------------------------------- • 1 voidGraph::BellmanFord(constintn, constintv) • 2 // 음의 길이 간선을 가지는 단일 시발점 모든 종점 • //최단 경로 • 3 { • 4 for(inti=0; i<n; i++) dist[i] = length[v][i]; // dist 초기화 • 5 for(intk=2; k<=n-1; k++) • 6 for(u!=v이고 최소한 하나의 진입 간선을 갖는 u에 • 대해) • 7 for(그래프의 각 <i,u>에 대해) • 8 if(dist[u]>dist[i]+length[i][u]) dist[u] = dist[i] + length[i][u]; • 9 } • ----------------------------------------- • 프로그램 6.9: 최단 경로를 계산하는 Bellman과 Ford 알고리즘 • - BellmanFord의 분석 • •인접 행렬 O(n3), 인접 리스트 O(ne)
6.4 최단경로와 이행적 폐쇄 • ▶ 모든 쌍의 최단경로 • - u≠v인 모든 정점의 쌍 u와 v간의 최단경로를 구하는 것 • Ak[i][j] = min{Ak-1[i][j], Ak-1[i][k] + Ak-1[k][j]}, k≥0 • A-1[i][j] = length[i][j] • ----------------------------------------- • 1 voidGraph::AllLengths(constintn) • 2 // length[n][n]은 n개의 정점을 가진 그래프의 인접 행렬 • 3 // a[i][j]는 i와 j 사이의 최단 경로의 길이 • 4 { • 5 for(inti=0; i<n; i++) • 6 for(intj=0; j<n; j++) • 7 a[i][j] = length[i][j]; // length를 a에 복사 • 8 for(intk=0; k<n; k++) // 제일 큰 정점의 인덱스가 k인 경 //로에 대해 • 9 for(i=0; i<n; i++) // 가능한 모든 정점의 쌍에 대해 • 10 for(intj=0; j<n; j++) • 11 if((a[i][k]+a[k][j])<a[i][j]) a[i][j] = a[i][k] + a[k][j]; • 12 } • ----------------------------------------- • 프로그램 6.10: 모든 쌍의 최단경로 • - AllLengths의 분석 • •전체 시간은 O(n3)
6.4 최단경로와 이행적 폐쇄 • - 예제 6.7 • 그림 6.31: 모든 쌍의 최단 경로 문제의 예