ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준 5917] Roadblock
    C 프로그래밍/BOJ 2022. 9. 15. 22:04
    728x90

    https://www.acmicpc.net/problem/5917

     

    5917번: Roadblock

    Every morning, FJ wakes up and walks across the farm from his house to the barn. The farm is a collection of N fields (1 <= N <= 100) connected by M bidirectional pathways (1 <= M <= 10,000), each with an associated length. FJ's house is in field 1, and th

    www.acmicpc.net

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    int N, M;
    int farm[100 + 10][100 + 10];
    int chk[100 + 10];
    int path[100 + 10];
    int change[100 + 10];
    int num;
    int min_len;
    
    struct _st
    {
    	int n;
    	int d;
    };
    
    struct COMP
    {
    	bool operator()(_st &a, _st &b) {
    		return a.d > b.d;
    	}
    
    };
    
    using namespace std;
    
    priority_queue<_st, vector<_st>, COMP> PQ;
    
    
    void input(void)
    {
    	scanf("%d %d", &N, &M);
    	for (int i = 0; i < M; i++) {
    		int A = 0; int B = 0; int L = 0;
    		scanf("%d %d %d", &A, &B, &L);
    		farm[A][B] = L;
    		farm[B][A] = L;
    	}
    }
    
    
    int BFS(void)
    {
    	PQ = {};
    	fill(chk + 1, chk + 1 + N, 0x7fffffff);
    
    	PQ.push({ 1, 0 });	// 항상 존의 집에서부터 시작
    	chk[1]= 0;
    
    	while (!PQ.empty()) {
    		_st data = PQ.top();
    		PQ.pop();
    
    		if (data.n == N) return data.d;
    
    		for (int i = 1; i <= N; i++) {
    			if (farm[data.n][i] == 0) continue;	// 연결되지 않은 노드 건너뜀
    			int nd = data.d + farm[data.n][i];
    			if (chk[i] <= nd) continue;
    			chk[i] = nd;
    			path[i] = data.n;
    			PQ.push({ i, nd });
    		}
    	}
    }
    
    void get_route(int n)
    {
    	if (n == 0) {
    		return;
    	}
    	get_route(path[n]);
    	change[num] = n;
    	num++;
    	//printf("%d ", n);
    }
    
    
    int get_min(void)
    {
    	int disturb = 0;
    	for (int i = 0; i < num - 1; i++) {
    		farm[change[i]][change[i + 1]] *= 2;
    		farm[change[i + 1]][change[i]] *= 2;
    		int sub = BFS() - min_len;
    		disturb = (disturb < sub) ? sub : disturb;
    		farm[change[i]][change[i + 1]] /= 2;
    		farm[change[i + 1]][change[i]] /= 2;
    	}
    	return disturb;
    }
    
    
    
    int main()
    {
    	input();
    	min_len = BFS();
    	get_route(N);
    	int ans = get_min();
    	printf("%d\n", ans);
    	return 0;
    }

    ㅇ...영어....=_=...

    문제 설명을 대충하자면

    FJ의 집 1에서 헛간 N으로 가는 최단 경로를 구하는 문제인데, 특정 두 노드 사이의 경로를 2배하여 ( "한 경로의 길이를 2배하여 구한 새로운 최단거리" - "집에서 헛간까지의 최단경로 길이") 의 최대값을 구해야 한다. 

     

     

    // input( ) 함수

    사실 인접리스트로 구현해보고 싶었지만 그건 실패했다.. 만약 해당 방법으로 푼다면 공유하겠다. 

    farm이라는 인접행렬에 두 노드 A, B와 경로 L을 삽입한다. B 와 A 도 같은 거리만큼 떨어져 있으므로 반대로도 삽입해준다. 

     

     

    // BFS( ) 함수

    이 함수는 농부 존의 집 1에서부터 헛간 N까지의 최단경로를 구하는 일을 한다. 

    이때 주의할 점은 한번 최단 경로를 구하고 더이상 함수를 쓰지 않는 것이 아니라, get_min 함수에서 계속해서 호출하기 때문에 PQ와 chk배열의 초기화가 항상 필요하다. 

    한편 큐가 아니라 우선순위 큐를 사용했기 때문에, 모든 경로를 탐색하며 경우의 수를 따질 필요 없이 PQ에서 방금 뺀 데이터의 노드가 N과 같으면 바로 리턴해주어도 된다. 경로가 작은 것을 우선적으로 탐색하여 N까지 도달한 것이기 때문에, 더 진행하는 것이 의미가 없는 것이다. 

     

     

    // get_route( ) 함수

    사실 모든 경로를 2배씩 해서 그때마다의 최단 거리를 구해도 되지만... 이는 의미가 없다. 

    예제를 살펴보자. 

    // input
    5 7
    2 1 5
    1 3 1
    3 2 8
    3 5 7
    3 4 3
    2 4 7
    4 5 2
    
    // output
    2

    이 경우 최단 거리는 6이고, 지나온 경로는 1 -> 3 -> 4 -> 5 이다. 

    따라서 다른 간선을 2배해줘도 어차피 그쪽으로 가지 않을 것이기 때문에, 그때마다 최단 거리는 6이고 경로도 동일할 것이다. 

    따라서 (1, 3) (3, 4) (4, 5) 노드 사이의 경로만 2배를 해주고, 각 경우들마다의 최단거리를 구해줄 것이다. 

     

     

    // get_min( ) 함수

    change는 지나온 경로{1, 3, 4, 5}가 들어있는 배열이다. 

    두 노드 사이의 거리를 2배 해주고, 다시 BFS 함수를 호출하여 최단거리를 구해준다. 리턴값과 원래의 최단거리(min_len) 사이의 차를 sub 변수에 담아주었다. 

    또한 그 차가 최대가 되는 경우를 출력해야 하기 때문에, disturb라는 변수에 차의 최댓값을 담아주도록 했다.

    다음 두 노드 사이의 거리를 2배 해주고 BFS 함수를 호출하여 최단거리를 구하기 위해, 위에서 2배해주었던 경로들을 다시 2로 나누어 원래대로 바꿔주는 것이 필요하다. 

     

    728x90

    'C 프로그래밍 > BOJ' 카테고리의 다른 글

    [백준 6987] 월드컵  (0) 2022.09.18
    [백준 2580] 스도쿠  (1) 2022.09.18
    [백준 1753] 최단 거리  (0) 2022.09.15
    [백준 1655] 가운데를 말해요  (0) 2022.09.15
    [백준 17141] 연구소 2  (0) 2022.09.15

    댓글

Designed by Tistory.