[BOJ] 중량제한

Date:

[BOJ] 중량제한

Problem URL : 중량제한

풀이 1 (파라메트릭 서치)

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <cstring>

using namespace std;

vector<pair<int,int>> v[10001];
int n, m;
bool visit[10001];
int start, finish;

bool isPass(int weight) {
	memset(visit, false, sizeof(visit));
	visit[start] = true;
	queue<int> q;
	q.push(start);
	while (!q.empty()) {
		int cur = q.front();
		q.pop();
		if (cur == finish) return true;
		for (int i = 0; i < v[cur].size(); i++) {
			int next = v[cur][i].first;
			int nextW = v[cur][i].second;
			if (visit[next] || weight > nextW) continue;
			q.push(next);
			visit[next] = true;
		}
	}

	return false;
}

int main() {
	ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
	cin >> n >> m;
	int maxW = 0;
	for (int i = 0; i < m; i++) {
		int a, b, c;
		cin >> a >> b >> c;
		v[a].push_back({ b,c });
		v[b].push_back({ a,c });
		maxW = max(maxW, c);
	}
	cin >> start >> finish;

	int low = 0, high = maxW;
	int ans = 0;
	while (low <= high) {
		int mid = (low + high) / 2;
		if (isPass(mid)) {
		// 통과하면 중량을 높혀본다
			ans = mid;
			low = mid + 1;
		} else {
		// 통과실패하면 중량을 낮혀본다
			high = mid - 1;
		}
	}
	cout << ans << endl;

	return 0;
}

풀이 2 (크루스칼, Union-Find)

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

struct bridge {
    int start, finish, cost;
    bool operator < (const bridge& other) {
        return cost < other.cost;
    }
};

int n, m;
vector<bridge> bridges;

int group[10001];

int find(int p) {
    if (group[p] == p) return p;
    return group[p] = find(group[p]);
}

void merge(int p, int q) {
    p = find(p);
    q = find(q);
    group[p] = q;
}

int solution(int start, int finish) {
    for (int i = 1; i <= n; i++) group[i] = i;
    //내림차순 정렬
    sort(bridges.rbegin(), bridges.rend());
    /*중량제한이 큰 다리순으로 연결(merge)해보면서
     출발점과 도착점이 같은 group에 속하게 되는지 확인한다*/
    for (int i = 0; i < bridges.size(); ++i) {
        merge(bridges[i].start, bridges[i].finish);

        if (find(start) == find(finish)) {
            return bridges[i].cost;
        }
    }
    /*찾아낸 다리를 x라고 하자.
    x보다 큰 다리들만으로는 출발점과 도착점이 연결되지 않았다는 뜻이다 */
    return 0;
}

int main() {
    ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);    
    cin >> n >> m;
    while (m--) {
        int a, b, c;
        cin >> a >> b >> c;
        bridges.push_back({ a, b, c });
    }

    int start, finish;
    cin >> start >> finish;
    cout << solution(start, finish) << endl;
    
    return 0;
}

Comments

풀이 2가 풀이 1보다 2배 이상 빠르다! Union-Find를 이용한 알고리즘이 확실히 아이디어가 좋다.

댓글