mojo's Blog

[백준 11378] 열혈강호 4 본문

백준/Graph

[백준 11378] 열혈강호 4

_mojo_ 2021. 11. 10. 20:43

문제 링크 => 11378번: 열혈강호 4 (acmicpc.net)

 

11378번: 열혈강호 4

첫째 줄에 직원의 수 N과 일의 개수 M, 지난달에 받은 벌점의 합 K가 주어진다. (1 ≤ N, M ≤ 1,000, 1 ≤ K ≤ N) 둘째 줄부터 N개의 줄의 i번째 줄에는 i번 직원이 할 수 있는 일의 개수와 할 수 있는

www.acmicpc.net

 

최대 유량 문제이다.

 

이 문제는 열혈강호 3 문제에서 약간의 변형이 이루어진 문제이다.

 

열혈강호 3 문제에서는 K 명은 최대 일을 2개 할 수 있다고 되어있다.

 

그러나 열혈강호 4 문제에서는 K 명이 동일하게 일을 2개 할 수 있거나 한명에게 몰빵하여 최대 (K + 1)개를 할 수 있다는 점에 있다.

 

이를 에드몬드-카프 알고리즘을 활용하여 다음과 같이 간선을 연결해줘야 한다.

 

 

 

 

열혈 강호 3 문제에서는 다음과 같이 간선과 capacity를 잡았다.

 

S <=> T 에 대한 간선의 capacity를 K로 잡고 (capacity[S][T] = K, 직원들 전부 추가로 일한 양의 합 = K)

T <=> ei 에 대한 간선의 capacity를 1로 잡음 (capacity[T][ei] = 1, 직원이 추가로 할 수 있는 최대 일의 양 = 1)

 

그러나 열혈 강호 4 문제에서는 다음과 같이 간선과 capacity를 잡아야 한다.

 

S <=> T 에 대한 간선의 capacity를 K로 잡고 (capacity[S][T] = K, 직원들 전부 추가로 일한 양의 합 = K)

T <=> ei 에 대한 간선의 capacity를 동일하게 K로 잡음 (capacity[T][ei] = K, 직원이 추가로 할 수 있는 최대 일의 양 = K)

 

 

Solution Code

 

#define _CRT_SECURE_NO_WARNINGS
#include <queue>
#include <iostream>
#include <vector>

using namespace std;

const int S = 0, E = 2001;
int capacity[2022][2022], flow[2022][2022], d[2022];
vector<int> v[2022];

void initialize(int N, int M, int K)
{
	int i;
	// from dummy(start) to employee
	// from dummy(K) to employee
	// dummy(start) : 0, dummy(K) : 2002
	for (i = 1; i <= N; i++) {
		v[S].push_back(i), v[i].push_back(S);
		capacity[S][i] = 1;
		v[E + 1].push_back(i), v[i].push_back(E + 1);
		capacity[E + 1][i] = K;
	}
	v[S].push_back(E + 1), v[E + 1].push_back(S);
	capacity[S][E + 1] = K;

	// from job to dummy(end)
	// dummy(end) : 2001
	for (i = 1001; i <= 1000 + M; i++) {
		v[i].push_back(E), v[E].push_back(i);
		capacity[i][E] = 1;
	}
}

void fill_d(int d[], int size)
{
	int i;
	for (i = 0; i <= size; i++)
		d[i] = -1;
}

int maxFlow(int start, int end)
{
	int i, cur, max_flow, min_flow;

	max_flow = 0;
	while (1) {
		fill_d(d, end + 1);
		queue<int> Q;
		Q.push(start);

		while (!Q.empty()) {
			cur = Q.front(), Q.pop();
			for (int next : v[cur]) {
				if (d[next] == -1 && capacity[cur][next] - flow[cur][next] > 0) {
					Q.push(next), d[next] = cur;
					if (next == end)
						break;
				}
			}
		}

		if (d[end] == -1) return max_flow;

		min_flow = 1000000000;
		for (i = end; i != start; i = d[i]) {
			min_flow = min(min_flow, capacity[d[i]][i] - flow[d[i]][i]);
		}

		max_flow += min_flow;
		for (i = end; i != start; i = d[i]) {
			flow[d[i]][i] += min_flow;
			flow[i][d[i]] -= min_flow;
		}
	}
}

int main()
{
	ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);

	int N, M, K, job_cnt, job;
	cin >> N >> M >> K;
	initialize(N, M, K);
	for (int i = 1; i <= N; i++) {
		cin >> job_cnt;
		for (int j = 0; j < job_cnt; j++) {
			cin >> job;
			v[i].push_back(1000 + job), v[1000 + job].push_back(i);
			capacity[i][1000 + job] = 1;
		}
	}
	cout << maxFlow(S, E);

	return 0;
}

 

'백준 > Graph' 카테고리의 다른 글

[백준 11779] 최소비용 구하기 2  (0) 2021.12.01
[백준 23743] 방탈출  (0) 2021.11.30
[백준 2056] 작업  (0) 2021.11.08
[백준 6087] 레이저 통신  (0) 2021.11.06
[백준 1922] 네트워크 연결  (0) 2021.11.05
Comments