BOJ 백준 2316 : 도시 왕복하기 2
Updated:
시작하면서
이번 문제는 네트워크 유량/최대 유량(Network Flow) 과 관련된 문제이다.
문제 이해
네트워크 유량/최대 유량(Network Flow) 문제는 포드-풀커슨 알고리즘(Ford-Fulkerson)/에드몬드-카프 알고리즘(Edmonds-Karp Algorithm) 으로 해결할 수 있다. 개념은 해당 블로그를 참조하도록 한다.
이 문제는 앞에서 풀었던 도시 왕복하기 1 문제의 확장판이다. 문제에서 중요하게 봐야할 점은 다음 조건들이다.
- 한 도시를 두 번 이상 방문하지 않아야 함
- 한 개 이상의 도시를 중간에 거쳐야 함
1번 조건을 충족하기 위해, 한 정점을 들어오는 in 정점, out 정점 2개로 나누어서 용량 1의 간선으로 연결한다. 그리고 마을과 마을을 이을 때에는 out->in, in->out 방향으로 용량 1의 간선을 이어서 문제를 해결한다.
해결
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <limits.h>
using namespace std;
#define MAX_SIZE (801)
int DoEdmondKarp(const vector<vector<int> >& graph, const vector<vector<int> >& capacity, const int kOutIndex)
{
const int kSource = 401;
const int kSink = 2;
vector<vector<int> > flow(MAX_SIZE);
for (int i = 1; i < flow.size(); i++)
{
flow[i].resize(MAX_SIZE);
}
int result = 0;
while (true)
{
vector<int> p(MAX_SIZE, -1);
p[kSource] = kSource;
queue<int> queue;
queue.push(kSource);
while (queue.empty() == false)
{
int current = queue.front(); queue.pop();
for (int i = 0; i < graph[current].size(); i++)
{
int next = graph[current][i];
if (capacity[current][next] - flow[current][next] > 0 && p[next] == -1)
{
p[next] = current;
queue.push(next);
if (next == kSink)
{
break;
}
}
}
}
if (p[kSink] == -1)
{
break;
}
int minimumFlow = INT_MAX;
for (int i = kSink; i != kSource; i = p[i])
{
minimumFlow = min(minimumFlow, capacity[p[i]][i] - flow[p[i]][i]);
}
for (int i = kSink; i != kSource; i = p[i])
{
flow[p[i]][i] += minimumFlow;
flow[i][p[i]] -= minimumFlow;
}
result += minimumFlow;
}
return result;
}
int main()
{
// sync off
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// sync off
vector<vector<int> > graph;
vector<vector<int> > capacity;
int N, P;
cin >> N >> P;
const int kOutIndex = 400;
capacity.resize(MAX_SIZE);
for (int i = 1; i <= capacity.size(); i++)
{
capacity[i].resize(MAX_SIZE);
}
graph.resize(801);
for (int i = 1; i <= N; i++)
{
graph[i].push_back(kOutIndex + i);
graph[kOutIndex + i].push_back(i);
capacity[i][kOutIndex + i] = 1;
}
const int kCapacity = 1;
for (int i = 0; i < P; i++)
{
int from, to;
cin >> from >> to;
graph[from + kOutIndex].push_back(to);
graph[to].push_back(from + kOutIndex);
graph[to + kOutIndex].push_back(from);
graph[from].push_back(to + kOutIndex);
capacity[from + kOutIndex][to] = kCapacity;
capacity[to + kOutIndex][from] = kCapacity;
}
cout << DoEdmondKarp(graph, capacity, kOutIndex);
return 0;
}
Leave a comment