넘치게 채우기

[BOJ] 24512 - Bottleneck Traveling Salesman Problem (Small) 본문

PS/BOJ

[BOJ] 24512 - Bottleneck Traveling Salesman Problem (Small)

riveroverflow 2025. 7. 5. 00:39
728x90
반응형

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

BOJ - Bottleneck Traveling Salesman Problem (Small)

문제 유형: TSP(Traveling Salesman Problem), 브루트포스, 백트래킹

문제 난이도: Silver II

시간 제한: 1초

메모리 제한: 1024

 

문제

외판원 순회 문제는 영어로 Traveling Salesman Problem (TSP) 라고 불리는 문제로 computer science 분야에서 가장 중요하게 취급되는 문제 중 하나이다. 이 중 변종 문제 중 하나인 Bottleneck Traveling Salesman Problem (BTSP) 문제를 살펴보자.

정점의 개수가 N개, 비용이 있는 간선이 M개인 방향 그래프가 주어진다. 어느 한 정점에서 출발해, 출발한 정점을 제외한 N−1개의 정점을 모두 한 번씩 방문하고 다시 처음 정점으로 돌아오는 순회를 찾으려고 한다. 이러한 순회는 여러 가지가 있을 수 있는데, 정점 간 이동 비용의 최댓값을 최소화하려고 한다.

그래프가 주어졌을 때, 정점 간 이동 비용의 최댓값을 최소화하면서 모든 정점을 방문하는 순회를 찾아보자.

 

입력

첫 번째 줄에는 정점의 개수 N과 간선의 개수 M이 주어진다. (2≤N≤9, 0≤M≤N(N−1))

두 번째 줄부터 M개의 줄에 걸쳐서 간선에 대한 정보가 세 정수 u, v, c로 주어진다. 이는 정점 u에서 v로 향하는 비용이 c인 간선이 있음을 의미한다. 두 정점 사이에 같은 방향의 간선이 2개 이상 존재하지 않는다. (1≤u,v≤N, u≠v, 1≤c≤5000000)

 

출력

모든 정점을 방문하는 순회가 있다면 첫 번째 줄에 정점 간 이동 비용의 최댓값의 최솟값을 출력한다. 만약에 이러한 순회가 없는 경우 -1을 출력한다.

모든 정점을 방문하는 순회가 있다면, 다음 줄에 정점 간 이동 비용의 최댓값을 최소화하도록 방문해야 하는 정점 번호를 순서대로 N개를 출력한다. 이러한 순회가 여러 가지가 있는 경우 아무것이나 출력해도 된다.

 

풀이

모든 경우의 수를 구하면 된다.

어차피 한 바퀴를 돌아야하므로, 시작점을 1로 고정해도 상관없다.

방문한 적이 없으면, 방문처리하고 깊이방문한뒤 돌아와서 방문을 취소해주는 식으로 하면 된다.

 

코드

C++

#include <bits/stdc++.h>

using namespace std;
using pii = pair<int, int>;

int ans = INT_MAX;
vector<int> ans_trace;
int n, m;

bool visitedall(vector<bool> &visited) {
    for (int i = 1; i <= n; i++) {
        if (!visited[i]) return false;
    }
    return true;
}

void dfs(int node, int cost, vector<vector<pii>> &adj, vector<bool> &visited,
         vector<int> &trace) {
    if (node == 1 && visitedall(visited)) {
        if (cost < ans) {
            ans_trace = trace;
            ans = cost;
        }
        return;
    }
    for (const auto &[e, w] : adj[node]) {
        if (!visited[e]) {
            visited[e] = true;
            trace.emplace_back(e);
            dfs(e, max(cost, w), adj, visited, trace);
            trace.pop_back();
            visited[e] = false;
        }
    }
}

int main(int argc, char *argv[]) {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    cin >> n >> m;

    vector<vector<pii>> adj(n + 1);
    vector<bool> visited(n + 1, false);
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        adj[u].emplace_back(v, w);
    }

    vector<int> trace = {1};
    dfs(1, -1, adj, visited, trace);

    if (ans == INT_MAX) {
        cout << "-1\n";
        return 0;
    }
    cout << ans << "\n";
    for (int i = 0; i < ans_trace.size() - 1; i++) {
        cout << ans_trace[i] << " ";
    }
    cout << "\n";

    return 0;
}
728x90
반응형

'PS > BOJ' 카테고리의 다른 글

[BOJ] 2161 - 카드 1  (0) 2025.07.07
[BOJ] 22253 - 트리 디자이너 호석  (0) 2025.07.06
[BOJ] 2009 - Minecraft  (0) 2025.07.04
[BOJ] 2876 - 그래픽스 퀴즈  (0) 2025.07.02
[BOJ] 25193 - 곰곰이의 식단 관리  (0) 2025.07.01