SW/Algorithm

BFS, 가중치 있는 map

Gangdor 2021. 8. 3. 19:21
반응형

문제

주어지는 노드사이에는 최대 1개의 도로가 있으며 양방향 도로이다.

도로에는 가중치가 있으며 노드간 이동시에는 최단 경로로 이동한다.

N, 노드 수 : 5~100

M, 도로 수 : 5~5000

D, 노드 사이의 거리

 

이때 각 노드를 출발점으로 할때 도착 노드까지의 거리가 가장 먼 거리를 X라고 하자.

노드 중의 X가 가장 작은 X의 값을 구하라 

 

입력

N과 M이 입력되며

노드A와 노드 B 사이의 거리 D가 아래와 같이 입력된다.

5 7

1 2 5

3 2 14

2 4 5

1 3 10

4 3 15

5 4 15

3 5 8

 

출력

15

입력을 그래프로 표현하면 위와 같다.


접근방식

서로 다른 가중치가 있는 맵이므로 BFS로 접근이 유효하다.

BFS는 크게 2가지 종류가 있는데, 가중치가 서로 다른 경우와 가중치가 같은 경우가 그것이다.

- 가중치가 다를 경우 : 확산시 중복방문을 허용해야한다. 단 무조건 중복방문을 허용할 수는 없으며 visit배열에

방문 표시가 아닌 누적치를 저장한다. 또한 visit에 저장된 누적치보다 확산할 경로의 누적치가 더 이로울 경우에만 확산한다.

- 가중치가 같을 경우 : 가중치가 같다면 중복방문이 필요 없다.

 

1. 노드와 간선정보는 이차원배열로 표현할 수 있다. 입력정보를 이차원 배열로 표현한다.

2. 출발점으로 각 노드를 BFS로 탐색하며 각 출발점 마다의 X값을 구한다.

3. 단, 확산시 기존에 visit배열 보다 확산할 노드가 이로울 경우만 확산한다. (따라서 누적치 visit 배열을 특정 최대값으로 초기화할 필요가 있다.)

 

※ BFS 포멧

1) read point, write point, visit배열 등 초기화

2) 시작 노드 Enque

3) while(rp<wp) 동안 확산 + 확산 조건 및 Return 조건

 

 

원리

1) Enque시에 visit배열에 노드의 가중치 누적을 저장한다. (=이전 경로)

2) Deque하면서 기존 visit 배열에 저장된 누적치(=이전경로)보다 이로울 시 Data를 갱신한다.

 

 

#include <stdio.h>
#define MAX 100*100+10
int N; //공장수
int M; //도로수
int map[100+10][100+10];
int que[100*100*100];
int visit[100+10];
int A[5000];
int B[5000];
int D[5000];
int rp;
int wp;

void Input(){
	
	
	scanf("%d",&N);
	scanf("%d",&M);
	for(int i=1; i<=M; i++){
		//scanf("%d %d %d", &A[i], &B[i], &D[i]);
		scanf("%d", &A[i]);
		scanf("%d", &B[i]);
		scanf("%d", &D[i]);
	}
	
	MakeMap(A,B,D);
}

void MakeMap(int* A, int* B, int* D){
	//초기화
	for(int i=0; i<=N; i++){
		for(int j=0; j<=N; j++){
			if(i==j) map[i][j] =0;
			else map[i][j]=MAX;
			//map[i][j] =0;
		}
	}
	
	for(int i=1; i<=M; i++){
		map[A[i]][B[i]] = map[B[i]][A[i]]= D[i];
	}
	
}

void Enque(int node){
	que[wp++]=node;
}

int Deque(){
	return que[rp++];
}

int BFS(int sp){
	//초기화
	rp=0;
	wp=0;
	for(int i=1; i<=N; i++){
			visit[i] = MAX;
	}

	//시작점
	Enque(sp);
	visit[sp]=0;
	
	//확산
	while(rp<wp){
		int cur = Deque();
		for(int i=1; i<=N; i++){
			if(visit[i]> visit[cur]+map[cur][i]){
				visit[i]=visit[cur]+map[cur][i];
				Enque(i);//방문
			}
		}
		
	}
	
	int rtn=0;
	for(int i=1; i<=N; i++){
		if(rtn<visit[i])
			rtn = visit[i];
	}
	
	return rtn;
	
}

int main() {
	Input();
	//MakeMap();
	int ans = MAX;
	
	for(int i=1; i<=N; i++){
		int temp = BFS(i);	
		//printf("temp : %d\n",temp);
		if(ans>temp) ans = temp;
	}
	
	printf("%d\n", ans);
	
	/*
	printf("+++++++++++++++++\n");
	for(int j=1; j<=N; j++){
			printf("%d\t", visit[j]);
	}
	
	for(int i=1; i<=N; i++){
		for(int j=1; j<=N; j++){
			printf("%d\t\t", map[i][j]);
		}
		printf("\n");
	}
	*/
	
	return 0;
}

 

반응형

'SW > Algorithm' 카테고리의 다른 글

스택활용하기, 꼬리잡기  (0) 2021.08.06
Greedy 알고리즘  (0) 2021.08.05
DFS+간단테크닉 문제 혹은 DFS+BFS  (0) 2021.08.02
DP문제, 빵먹기  (0) 2021.07.28
DFS 조합, 모든 경우의 수  (0) 2021.07.27