PS/백준

[백준] 1671 상어의 저녁식사 (C++)

dong_gas 2022. 2. 12. 22:01

신촌연합 중급반 연습문제로 풀다가 푼 문제.

 

1671번: 상어의 저녁식사

어떤 상어는 저녁식사로 서로를 먹는다. 모든 상어는 자신과 다른 상어의 크기, 속도, 지능을 수치로 나타낸 것을 알고 있다. 만약, 상어 A의 크기, 속도, 지능이 상어 B의 크기, 속도, 지능보다 크

www.acmicpc.net

 

문제 요약)

N마리의 상어가 있다.

N마리의 상어는 크기, 속도, 지능이 있다. 이 세 개 모두 다른 상어보다 크거나 같으면 다른 상어를 먹을 수 있다.

각 상어는 최대 2마리까지 먹을 수 있다.

남아있는 상어가 최소가 되게 먹었을 때, 남아있는 상어의 수는?

 

 

1.

상어가 다른 상어를 먹는다...

각 상어가 최대 2마리까지 먹을 수 있음...

최대한 많이 먹어야 함...

 

 

2.

이거 어디서 본 상황이다. 플로우가 떠오른다.

https://www.acmicpc.net/problem/11376 (열혈강호 2)

 

 

3.

각 상어마다 노드를 2개씩 주자.

하나는 먹는 쪽, 하나는 먹히는 쪽.

소스 -> 먹는 쪽에 2의 용량을 주자. 2개까지 먹을 수 있으므로

먹을 수 있는 것들을 간선으로 이어주자.

모든 먹히는 쪽 -> 싱크에 1의 용량을 주자. 1이 흘러들어오면 먹힌 것이다.

이분매칭을 이용해서도 풀 수 있을 것처럼 생겼다. (가능)

 

 

4.

답은 (N-최대유량)이다. 최대유량 값은 먹힌 상어의 수이므로!

 

 

코드

더보기
#include <bits/stdc++.h>
#define endl '\n'
#define MOD 998244353
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;

struct str {
	ll a, b, c;
};

ll n;
ll cap[110][110];   //용량
ll flow[110][110];
ll cache[110];      //이전 노드 저장하는 용도
vector<ll> adj[110];
vector<str> jaws(51);

void add_edge(ll from, ll to, ll c) {
	adj[from].push_back(to);
	adj[to].push_back(from);
	cap[from][to] = c;
}

ll Edmond_Karp(ll source, ll sink) {
	ll max_flow = 0;
	while (1) {
		queue<ll> q;
		q.push(source);
		memset(cache, -1, sizeof(cache));
		cache[source] = 0;
		while (q.size()) {
			ll cur = q.front();
			q.pop();
			for (auto nxt : adj[cur]) {
				if (cache[nxt] == -1 && cap[cur][nxt] - flow[cur][nxt] > 0) {
					cache[nxt] = cur;
					q.push(nxt);
					if (nxt == sink) break;
				}
			}
		}
		if (cache[sink] == -1) break;
		ll min_cap = 9876543210;
		for (ll i = sink; i != source; i = cache[i]) {
			ll bef = cache[i];
			min_cap = min(min_cap, cap[bef][i] - flow[bef][i]);
		}
		max_flow += min_cap;
		for (ll i = sink; i != source; i = cache[i]) {
			ll bef = cache[i];
			flow[bef][i] += min_cap;
			flow[i][bef] -= min_cap;
		}
	}
	return max_flow;
}

bool can_eat(ll i, ll j) {
	str x = jaws[i];
	str y = jaws[j];
	if (x.a == y.a && x.b == y.b && x.c == y.c) {
		if (i < j) return true;
		else return false;
	}
	if (x.a >= y.a && x.b >= y.b && x.c >= y.c) return true;
	else return false;
}

void solve() {
	cin >> n;
	for (ll i = 1; i <= n; i++) cin >> jaws[i].a >> jaws[i].b >> jaws[i].c;
	for (ll i = 1; i <= n; i++) {
		add_edge(0, i, 2);
		add_edge(n + i, 2 * n + 1, 1);
	}
	for (ll i = 1; i <= n; i++) {
		for (ll j = 1; j <= n; j++) {
			if (i == j) continue;
			if (can_eat(i, j)) add_edge(i, n + j, 1);
		}
	}
	cout << n - Edmond_Karp(0, 2 * n + 1) << endl;
}

int main() {
	ios::sync_with_stdio(0); cin.tie(0);
	int tc = 1; //cin >> tc;
	while (tc--) solve();
	return 0;
}

 

플로우. 멈춰!

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

[백준] 2041 숫자채우기  (2) 2022.03.03
[백준] 2325 개코전쟁, 2307 도로검문 (C++)  (4) 2022.02.13
[백준] 1017 소수 쌍 (C++)  (6) 2022.02.10
[백준] 10948 Daily 로또 (Text)  (2) 2021.12.14
[백준] 23560 약 (C++)  (0) 2021.11.16