728x90
트리 관련 개념 정리
신장트리와 최소비용 신장 트리
🟦신장트리 : n개 정점 무방향 그래프에서 간선 n-1개로 이루어진 부분 그래프
- 정점 n개, 간선 n-1개, 사이클X, 연결그래프(단절X)
🟦최소비용 신장 트리 : 무방향 가중치 그래프에서 신장 트리 구성 간선의 가중치 합이 최소인 그래프
- 1) 크루스칼 알고리즘
- (1) 가중치 높은 간선 제거하며 최소비용 만들기
- (2) 가중치 낮은 간선 삽입하며 최소비용 만들기
- 2) 프림 알고리즘
- (간선 정렬 X) 하나의 정점에서 시작하여 트리 확장해감
- 확장 정점들에 부속된 모든 간선들을 비교하며 가장 낮은 간선 연결 확장
🟪 최단 경로
🟦 최단 경로
- (신장트리가 아닌) 가중치 그래프에서 정점u와 정점 v를 잇는 경로 중 가중치 합이 최소인 경로
- 1) 다익스트라 최단 경로 알고리즘 | One-to-All
- : 시작 정점 하나에서 다른 모든 정점까지의 최단 경로 구하기
- (1) 시작 정점 에서 각 정점까지의 최단 경로 갖는 정점 u추가
- (2) 추가된 u를 거쳐가는 경로 VS 기존 경로 비교 후 더 작은 값으로 업데이트
- 2) 플로이드 최단 경로 알고리즘 | All-to-All
- : 모든 정점에서 다른 정점들 사이의 모든 최단 경로 구하기
9-5. 다익스트라 알고리즘 | 어려움
import java.util.ArrayList;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Scanner;
/* 9=5. 다익스트라 알고리즘 */
class Edge implements Comparable<Edge>{
public int vex;//정점
public int cost;//가중치
Edge(int vex, int cost){
this.vex = vex;
this.cost = cost;
}
@Override
public int compareTo(Edge o) {
// TODO Auto-generated method stub
return this.cost-o.cost; //비용 오름차순
}
}
public class Main1 {
static int n, m;
static ArrayList<ArrayList<Edge>> graph;
static int[] dis;
//솔루션 함수
public void solution(int v) {
PriorityQueue<Edge> pQ = new PriorityQueue<>();
pQ.offer(new Edge(v, 0));
dis[v]=0;//첫번째 방문 v는 0으로 처리 (: 시작정점)
while(!pQ.isEmpty()) {
Edge tmp = pQ.poll();//오르마순이므로 비용 최소가 poll됨
int now = tmp.vex;//현재 정점
int nowCost = tmp.cost;//현재 비용
if(nowCost > dis[now]) continue;
//현재 뽑은 now정점과 연결도니 그래프 엣지들 하나씩 뽑아서 돈다.
for(Edge ob : graph.get(now)) {
//기존 거리 > 현재 비용 + 새 비용
if(dis[ob.vex] > nowCost + ob.cost) {
dis[ob.vex] = nowCost + ob.cost; //갱신
pQ.offer(new Edge(ob.vex, nowCost+ob.cost));//새로운 edge 담음
}
}
}
}
//실행 메인
public static void main(String[] args) {
// TODO Auto-generated method stub
Main1 T = new Main1();
Scanner kb = new Scanner(System.in);
n = kb.nextInt();
m = kb.nextInt();
graph = new ArrayList<ArrayList<Edge>>();
for(int i=0; i<=n; i++) {
graph.add(new ArrayList<Edge>());
}
dis = new int[n+1];
//dis 배열을 모두 Max값으로 초기화
Arrays.fill(dis, Integer.MAX_VALUE);
for(int i=0; i<m; i++) {
int a= kb.nextInt();
int b= kb.nextInt();
int c = kb.nextInt();
//출발점 a에 연결될 정점 b와 비용 c를 담는다.
graph.get(a).add(new Edge(b, c));
}
T.solution(1);
for(int i=2; i<=n; i++) {
if(dis[i]!=Integer.MAX_VALUE) System.out.println(i+" : "+dis[i]);
else {
System.out.println(i+ "impossible");
}
}
}
}
9-6. 친구인가 | 서로소 집합| Union&Find
import java.util.Scanner;
/* 9-6. 친구인가 | 서로소 집합 Disjoint-Set: Union&Find 알고리즘 | */
public class Main2 {
static int[] unf;
//Find
public static int Find(int v) {
if(v==unf[v]) return v;
else return unf[v] = Find(unf[v]);
}
//Union
public static void Union(int a, int b) {
int fa = Find(a);
int fb = Find(b);
if(fa!=fb) unf[fa] = fb;
}
//실행 메인
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner kb= new Scanner(System.in);
int n = kb.nextInt();
int m = kb.nextInt();
//unf 초기화
unf = new int[n+1];
for(int i=1; i<=n; i++) unf[i]= i;
for(int i=1; i<=m; i++) {
int a= kb.nextInt();
int b= kb.nextInt();
Union(a,b);
}
int a= kb.nextInt();
int b= kb.nextInt();
int fa = Find(a);
int fb = Find(b);
if(fa == fb) System.out.println("YES");
else System.out.println("NO");
}
}
9-7. 원더랜드 | 크루스칼
/* 9-7. 원더랜드 (최소 스패팅 트리 - 크루스칼 : Union&Find 활용) */
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
//간선 정보 담을 객체
class Edge implements Comparable<Edge>{
public int v1;
public int v2;
public int cost;
Edge(int v1, int v2, int cost){
this.v1 = v1;
this.v2 = v2;
this.cost = cost;
}
@Override
public int compareTo(Edge o) {
// TODO Auto-generated method stub
return this.cost - o.cost; //비용 기준 오름차순 정렬
}
}
public class Main1 {
static int [] unf;
//Find
public static int Find(int v) {
if(v == unf[v]) return v;
else return unf[v] = Find(unf[v]);
}
//Union
public static void Union(int a, int b) {
int fa= Find(a);
int fb = Find(b);
if(fa != fb) unf[fa] = fb;
}
//실행 메인
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner kb = new Scanner(System.in);
int n = kb.nextInt();
int m = kb.nextInt();
unf = new int[n+1];
ArrayList<Edge> arr = new ArrayList<>();
for(int i=1; i<=n; i++) unf[i]= i;
for(int i=0; i<m; i++) {
int a = kb.nextInt();
int b = kb.nextInt();
int c = kb.nextInt();
arr.add(new Edge(a,b,c));
}
//최소비용 누적할 용
int answer = 0;
//비용 오름차순 정렬
Collections.sort(arr);
for(Edge ob : arr) {
int fv1 = Find(ob.v1); //v1의 집합 번호 받고
int fv2 = Find(ob.v2); //v2의 집합 번호 받음
//두 번호 동일한 경우 같은 집합 소속이므로 추가해서는 안됨
if(fv1 != fv2) { //둘이 다른 집합 소소의 정점인 경우에 한해서
answer += ob.cost;
Union(ob.v1, ob.v2);//둘을 한 집합으로 묶어서 추가하기
}
}
System.out.println(answer);
}
}
9-8. 원더랜드 | 프림
/* 9-8. 원더랜드 | 프림으로 풀기 : PriorityQueue 사용하기 */
import java.util.*;
class Edge1 implements Comparable<Edge1>{
public int vex;
public int cost;
Edge1(int vex, int cost) {
this.vex = vex;
this.cost = cost;
}
@Override
public int compareTo(Edge1 ob){
return this.cost-ob.cost;
}
}
class Main3 {
public static void main(String[] args){
Scanner kb = new Scanner(System.in);
int n=kb.nextInt();
int m=kb.nextInt();
ArrayList<ArrayList<Edge1>> graph = new ArrayList<ArrayList<Edge1>>();
for(int i=0; i<=n; i++){
graph.add(new ArrayList<Edge1>());
}
int[] ch=new int[n+1];
for(int i=0; i<m; i++){
int a=kb.nextInt();
int b=kb.nextInt();
int c=kb.nextInt();
graph.get(a).add(new Edge1(b, c));
graph.get(b).add(new Edge1(a, c));
}
int answer=0;
PriorityQueue<Edge1> pQ = new PriorityQueue<>();
pQ.offer(new Edge1(1, 0));
while(!pQ.isEmpty()){
Edge1 tmp=pQ.poll();
int ev=tmp.vex;
if(ch[ev]==0){
ch[ev]=1;
answer+=tmp.cost;
for(Edge1 ob : graph.get(ev)){
if(ch[ob.vex]==0) pQ.offer(new Edge1(ob.vex, ob.cost));
}
}
}
System.out.println(answer);
}
}
728x90
'알고리즘 이론 [개념] > [개념] 코테 알고리즘 공부 - 시즌 1' 카테고리의 다른 글
동적 계획 알고리즘 -(2) (0) | 2023.04.06 |
---|---|
동적 계획 알고리즘 -(1) (0) | 2023.04.03 |
그리디 알고리즘 섹션 - (2) (0) | 2023.03.31 |
그리디 알고리즘 섹션 - (1) (0) | 2023.03.30 |
DFS, BFS 활용 섹션 -(5) | 복습 (0) | 2023.03.29 |