[グリディ]クルーズ、プリムアルゴリズム
18175 ワード
1.最小長ツリー
2.クルーズアルゴリズム
https://www.youtube.com/watch?v=LQ3JHknGy8c
https://blog.naver.com/ndb796/221230994142
アルゴリズムの理解
https://velog.io/@jxlhe 46/アルゴリズム-Union-Find-Union-Find
コードで実現
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 각 정점의 부모 노드 번호를 저장하는 배열 (최종적으로는 루트 노드 번호)
int parent[10'000];
// 루트 노드를 찾는 Find 연산
int Find(int x) {
// 배열의 인덱스와 값이 같다면 루트 노드 발견!
if (x == parent[x]) return x;
// 부모 노드의 번호를 전달하면서, 루트 노드를 찾을 때까지 재귀 호출 반복
return parent[x] = Find(parent[x]);
}
// 두 노드를 같은 집합으로 합치는 Union 연산
void Union(int x, int y) {
x = Find(x);
y = Find(y);
// 루트 노드가 같다면 이미 연결되어 있는 것
if (x == y) return;
// 더 작은 값이 부모 노드가 될 수 있도록
if (x < y) parent[y] = x;
else parent[x] = y;
}
// 두 노드가 연결되어 있는지 판별하는 함수
bool isUnion(int x, int y) {
x = Find(x);
y = Find(y);
// 루트 노드가 같은지 확인
return (x == y);
}
// 하나의 간선 정보를 담는 클래스
class Edge {
public:
int node[2];
int weight;
Edge(int x, int y, int w) {
this->node[0] = x;
this->node[1] = y;
this->weight = w;
}
// 가중치가 작은 간선부터 MST에 추가하도록
bool operator < (Edge& edge) {
return this->weight < edge.weight;
}
};
int main() {
int V; // 정점 개수
scanf("%d", &V);
int E; // 간선 개수
scanf("%d", &E);
int x, y, w; // 하나의 간선을 이루는 두 정점의 번호와 가중치
vector<Edge> v;
for (int i = 0; i < E; i++){
scanf("%d %d %d", &x, &y, &w);
v.push_back(Edge(x, y, w)); // 객체 배열 생성
}
// 간선의 가중치를 기준으로 오름차순 정렬
sort(v.begin(), v.end());
// 각 정점의 번호 초기화
for (int i = 0; i < V; i++){
parent[i] = i;
}
int sum = 0;
for (int i = 0; i < v.size(); i++){
// 사이클이 발생하지 않을 때만 MST에 추가
if (!isUnion(v[i].node[0], v[i].node[1])) {
sum += v[i].weight;
Union(v[i].node[0], v[i].node[1]);
}
}
printf("%d\n", sum);
return 0;
}
じかんふくごうどぶんせき
出典:楊成峰、分かりやすいアルゴリズム、生エネルギー出版社、p.116
3.Primアルゴリズム
ぎじふごう
입력: 가중치 그래프 G=(V, E), |V|=n (정점 개수), |E|=m (간선 개수)
출력: 최소 신장 트리
1. 그래프 G에서 임의의 점 p를 시작점으로 선택, D[p]=0
// D[v]: T에 있는 점 u와 그 밖에 있는 점 v를 연결하는 간선 중에서 최소 가중치를 저장하는 배열
2. for(점 p가 아닌 각 점 v에 대해서){
3. if(그래프 상에 간선 (p, v)가 있으면)
4. D[v] = 간선 (p, v)의 가중치
5. else
6. D[v] = ∞
}
7. T = {p} // 임의의 점 p부터 시작
8. while(T에 있는 점의 수 < n) {
9. T에 속하지 않은 각 점 v에 대해서, D[v]가 최소인 점 v_min을 찾아 T에 추가
10. for(T에 속하지 않은 각 점 w에 대해서) {
11. if(간선 (v_min, w)의 가중치 < D[w])
12. D[w] = 간선 (v_min, w)의 가중치 // D[w] 갱신
}
}
13. return T // 최소 신장 트리 T 리턴
アルゴリズムの理解
じかんふくごうどぶんせき
8. while(T에 있는 점의 수 < n) {
9. T에 속하지 않은 각 점 v에 대해서, D[v]가 최소인 점 v_min을 찾아 T에 추가
10. for(T에 속하지 않은 각 점 w에 대해서) {
11. if(간선 (v_min, w)의 가중치 < D[w])
12. D[w] = 간선 (v_min, w)의 가중치 // D[w] 갱신
}
}
n個のノードが共有され,D[v]配列で重み付けが最も小さい点v minを線形ルックアップとして探すたびに,時間複雑度はO(n^2)である.
最短パスアルゴリズムと同様に,配列ではなく最小スタックデータ構造を用いて現在のノードから最小のv minを検索することで,時間複雑度をO(logV)に低減できる.
注意:https://www.weeklyps.com/entry/%ED%94%84%EB%A6%BC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Prims-algorithm
4.クルーズvs.プリムアルゴリズム
クルーズアルゴリズムは,幹線の重み値を昇順に並べた後,周期を形成しない幹線のみをMSTに順次追加する.逆にprimアルゴリズムはMSTに属さない頂点に重み付けの最小の頂点を追加した.
すなわち、クルーズアルゴリズムが周期なしに「幹線」を次々と追加する場合、primアルゴリズムはMSTに属さない「頂点」を次々と追加する.
別の角度から見ると、クルーズはn本の木が次第に1本の木に合併し、フリームは1本の木で、最終的に1本の木になったと考えている.
白俊1197号です。
https://www.acmicpc.net/problem/1197
Reference
この問題について([グリディ]クルーズ、プリムアルゴリズム), 我々は、より多くの情報をここで見つけました
https://velog.io/@jxlhe46/알고리즘-MST
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
입력: 가중치 그래프 G=(V, E), |V|=n (정점 개수), |E|=m (간선 개수)
출력: 최소 신장 트리
1. 그래프 G에서 임의의 점 p를 시작점으로 선택, D[p]=0
// D[v]: T에 있는 점 u와 그 밖에 있는 점 v를 연결하는 간선 중에서 최소 가중치를 저장하는 배열
2. for(점 p가 아닌 각 점 v에 대해서){
3. if(그래프 상에 간선 (p, v)가 있으면)
4. D[v] = 간선 (p, v)의 가중치
5. else
6. D[v] = ∞
}
7. T = {p} // 임의의 점 p부터 시작
8. while(T에 있는 점의 수 < n) {
9. T에 속하지 않은 각 점 v에 대해서, D[v]가 최소인 점 v_min을 찾아 T에 추가
10. for(T에 속하지 않은 각 점 w에 대해서) {
11. if(간선 (v_min, w)의 가중치 < D[w])
12. D[w] = 간선 (v_min, w)의 가중치 // D[w] 갱신
}
}
13. return T // 최소 신장 트리 T 리턴
8. while(T에 있는 점의 수 < n) {
9. T에 속하지 않은 각 점 v에 대해서, D[v]가 최소인 점 v_min을 찾아 T에 추가
10. for(T에 속하지 않은 각 점 w에 대해서) {
11. if(간선 (v_min, w)의 가중치 < D[w])
12. D[w] = 간선 (v_min, w)의 가중치 // D[w] 갱신
}
}
クルーズアルゴリズムは,幹線の重み値を昇順に並べた後,周期を形成しない幹線のみをMSTに順次追加する.逆にprimアルゴリズムはMSTに属さない頂点に重み付けの最小の頂点を追加した.
すなわち、クルーズアルゴリズムが周期なしに「幹線」を次々と追加する場合、primアルゴリズムはMSTに属さない「頂点」を次々と追加する.
別の角度から見ると、クルーズはn本の木が次第に1本の木に合併し、フリームは1本の木で、最終的に1本の木になったと考えている.
白俊1197号です。
https://www.acmicpc.net/problem/1197
Reference
この問題について([グリディ]クルーズ、プリムアルゴリズム), 我々は、より多くの情報をここで見つけました
https://velog.io/@jxlhe46/알고리즘-MST
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
Reference
この問題について([グリディ]クルーズ、プリムアルゴリズム), 我々は、より多くの情報をここで見つけました https://velog.io/@jxlhe46/알고리즘-MSTテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol