ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준 2307] 도로검문
    C 프로그래밍/BOJ 2022. 11. 24. 15:24
    728x90

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

     

    2307번: 도로검문

    그림 1은 어떤 도시의 주요 지점과 그 지점들 간의 이동시간을 나타낸 그래프이다. 그래프의 노드는 주요 지점을 나타내고  두 지점을 연결한 도로(에지)에 표시된 수는 그 도로로 이동할 때 걸

    www.acmicpc.net

    #include <cstdio>
    #include <queue>
    #include <list>
    int N, M;
    struct _st
    {
    	int n;
    	int t;
    };
    std::list<_st> L[1000 + 2];
    
    struct COMP
    {
    	bool operator()(const _st &a, const _st &b) {
    		return a.t > b.t;
    	}
    
    };
    std::priority_queue<_st, std::vector<_st>, COMP> PQ;
    int visited[1000 + 2];
    int route[1000 + 2];
    
    void input()
    {
    	scanf("%d %d", &N, &M);
    	for (int i = 0; i < M; i++) {
    		int a = 0, b = 0, t = 0;
    		scanf("%d %d %d", &a, &b, &t);
    		L[a].push_back({ b, t });
    		L[b].push_back({ a, t });
    	}
    }
    
    
    int no_chk()
    {
    	// init
    	PQ = {};
    	for (int i = 1; i <= N; i++) {
    		visited[i] = 0x7fffffff;
    		route[i] = -1;
    	}
    
    	PQ.push({ 1, 0 });
    	visited[1] = 0;
    	route[1] = -1;
    
    	while (!PQ.empty()) {
    		_st data = PQ.top();
    		PQ.pop();
    
    		if (data.n == N) return visited[N];
    
    		for (_st next : L[data.n]) {
    			if (visited[next.n] <= visited[data.n] + next.t) continue;
    			visited[next.n] = visited[data.n] + next.t;
    			PQ.push({ next.n, visited[next.n] });
    			route[next.n] = data.n;
    		}
    	}
    }
    
    
    int chk(int u, int v)	
    {
    	// init
    	PQ = {};
    	for (int i = 1; i <= N; i++) {
    		visited[i] = 0x7fffffff;
    	}
    
    	PQ.push({ 1, 0 });
    	visited[1] = 0;
    
    	while (!PQ.empty()) {
    		_st data = PQ.top();
    		PQ.pop();
    
    		if (data.n == N) return visited[N];
    
    		for (_st next : L[data.n]) {
    			if (visited[next.n] <= visited[data.n] + next.t) continue;
    			if (data.n == u && next.n == v) continue;
    			if (data.n == v && next.n == u) continue;
    			visited[next.n] = visited[data.n] + next.t;
    			PQ.push({ next.n, visited[next.n] });
    		}
    	}
    	return -1;
    }
    
    
    
    
    int choose_edge() 
    {
    	int max_time = 0;
    	for (int i = 1; i <= N; i++) {
    		if (route[i] == -1) continue;
    		int res = chk(route[i], i);	// u -> v, v -> u를 막는다  
    		if (res == -1) return -1;
    		if (res > max_time) max_time = res;
    	}
    	return max_time;
    }
    
    
    
    int main()
    {
    	input();
    	int time1 = no_chk();
    	//printf("%d", time1);
    	int time2 = choose_edge();
    	if (time2 == -1) printf("%d\n", -1);
    	else printf("%d\n", time2 - time1);
    	return 0;
    }

    원래는 인풋받은 모든 간선에 대하여 하나하나 검문을 해주는 코드를 작성했다. AC는 받았지만 실행시간이 1000ms나 되어 세상에서 제일 비효율적인 코드라는 생각에 공부 좀 하고 옴.. 

     

    이 문제는 모든 간선에 대하여 검문을 할 필요가 없다. 

    용의자가 최소 시간으로 N 에 도달하도록 하는 경로들 중에서 하나를 막았을 때, 얼마나 시간이 지연되는지 계산해주면 된다. 

    따라서 경로를 저장하기 위해 route라는 배열을 선언하고, -1로 초기화 해주었다. 만약 어떤 노드의 valuer가 -1이면 최소 시간으로 이동할 때, 해당 노드를 지나가지 않는다는 뜻이다. 

    route의 인덱스는 다음 노드 번호이고, route의 value는 현재 노드 번호이다. 

     

    이러한 처리 후 choose_edge에서 간선을 선택해줄 때는, 용의자가 지나가지 않는 간선을 검문하더라도 시간의 변화에는 아무 영향이 없으므로 continue한다. 용의자가 지나가는 간선에 대해서만 BFS 함수를 실행하여 N까지 도달하는데 걸리는 시간을 계산해주면 된다. 

     

    728x90

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

    [백준 20926] 얼음미로  (0) 2022.11.27
    [백준 4577] 소코반  (0) 2022.11.27
    [백준 10282] 해킹  (0) 2022.11.24
    [백준 1238] 파티  (0) 2022.11.23
    [백준 1697, 12851, 13549, 13913] 숨바꼭질1, 2, 3, 4  (0) 2022.11.22

    댓글

Designed by Tistory.