ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 1939(중량제한)
    전공/알고리즘 2020. 9. 30. 13:59

    www.acmicpc.net/problem/1939

     

    1939번: 중량제한

    첫째 줄에 N, M(1≤M≤100,000)이 주어진다. 다음 M개의 줄에는 다리에 대한 정보를 나타내는 세 정수 A, B(1≤A, B≤N), C(1≤C≤1,000,000,000)가 주어진다. 이는 A번 섬과 B번 섬 사이에 중량제한이 C인 다리

    www.acmicpc.net

    dfs와 bfs의 차이점과 특징을 상기시켜준 문제. 

     

    처음에는 그냥 dfs로 풀었다. 그러자 TLE

     

    최악의 경우에 거의 N*M의 시간복잡도를 가지므로, 10^9 시간초과 발생가능성이 존재한다. 따라서 시간을 더 줄일 방법을 찾아야 했다. 단순 탐색으로 풀게된다면 dfs나 bfs나 똑같이 된다. 따라서 다른 방법이 필요했다. 

     

    이진탐색을 이용해서 중량을 결정하고 탐색 가능 여부만 고르면 될까라고 생각을 했고, dfs+이분탐색으로 했지만 똑같이 TLE

     

    생각을 해보니 dfs는 끝나지 않는다. 재귀함수는 전체를 통제시키는 어떤 것이 없다. 뭐 설정을 해주면 있기야 하겠지만.. 일단 기본적으로는 존재하지 않아서 그 경로까지 가는길을 찾더라도 다른길을 가보게 된다. 따라서 bfs로 풀었다. 

     

    bfs는 queue에 넣어서 작동시키는 방법 재귀함수가 아닌 경우이기 때문에 한 함수에 대해서 종료만 시키면 모두 종료된다. 그래서 bfs로는 가능 여부가 더 쉽게 된다. 그리고 메모리 초과가 한 번 있었는데 단순하게 visited를 먼저 설정하느냐 후에 설정하느냐에 따라서도 메모리초과가 결정날 수 있겠구나 생각을 한다. 

     

    후에 하게되면 중복된 index가 게속해서 들어갈 수 있게된다.  따라서 먼저하자 

     

    #include<iostream>
    #include<vector>
    #include<utility>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define MAX 10005
    
    vector<pair<int, int> > graph[MAX];
    int start, fin;
    bool check[MAX];
    
    bool bfs(int weight) {
    	queue<int> q;
    	q.push(start);
    	check[start] = true;
    	while (!q.empty()) {
    		int num = q.front();
    		q.pop();
    		for (int i = 0; i < graph[num].size(); i++) {
    			if (check[graph[num][i].first] || graph[num][i].second < weight)continue;
    			if (graph[num][i].first == fin) {
    				return true;
    			}
    			check[graph[num][i].first] = true;
    			q.push(graph[num][i].first);
    		}
    	}
    	return false;
    }
    
    int main() {
    	int N, M;
    	cin >> N >> M;
    	for (int i = 0; i < M; i++) {
    		int a, b, c;
    		cin >> a >> b >> c;
    		graph[a].push_back(make_pair(b, c));
    		graph[b].push_back(make_pair(a, c));
    
    	}
    	cin >> start >> fin;
    
    
    	int right = 1000000000, left = 1, mid, ans = 0;
    
    	while (right >= left) {
    		for (int i = 0; i < MAX; i++)check[i] = false;
    		mid = (right + left) / 2;
    		if (bfs(mid)) {
    			left = mid + 1;
    			ans = mid;
    		}
    		else {
    			right = mid - 1;
    		}
    	}
    	cout << ans << '\n';
    }

    '전공 > 알고리즘' 카테고리의 다른 글

    백준 1309(동물원)  (0) 2020.10.04
    백준 10653(마라톤 2)  (0) 2020.10.02
    백준 5829(Luxury River Cruise)  (0) 2020.09.24
    백준 2252(줄 세우기)  (0) 2020.09.02
    백준 16207(직사각형)  (0) 2020.08.08

    댓글

Designed by Tistory.