문제
- 문제 링크
BOJ 4966 - Cards
$N$개의 카드 집합과 $M$개의 카드 집합이 주어진다.
주어진 규칙에 따라 카드 쌍을 제거하려 할 때, 카드 쌍이 가장 많이 제거되는 경우를 찾아보자.
TL : $2$ sec, ML : $512$ MB
$1 ≤ N, M ≤ 500$ $2 ≤ N_i, M_i ≤ 10^7$
알고리즘 분류
- 수학(math)
- 정수론(number_theory)
- 유클리드 호제법(euclidean)
- 이분 매칭(bipartite_matching)
풀이
$gcd(x, y) > 1$ 인 카드끼리 사이 좋게 제거할 수 있을 때, 가장 많이 제거 되도록 하는 경우를 찾으라고 한다.
파란색 카드 집합과 빨간색 카드 집합, 서로를 향해 간선을 세팅할 수 있고 $1 ≤ N, M ≤ 500$ 이므로..
이분 매칭 문제로 생각해 볼 수 있다.
각 카드 집합 간 모든 쌍에 대해 $gcd$를 검사 하고 그에 맞게 간선을 만들어주자.
이제 이분 매칭을 이용하면 최대 매칭 수를 $O(EV)$ 만에 찾아줄 수 있다.
$C$++이라 큰 걱정은 없다만.. 입력 포맷을 유의하자.
전체 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #include<bits/stdc++.h> #define N 501 using namespace std; vector <int> Gr[N]; int a[N], D[N], V[N]; int f(int p) { for (auto& a : Gr[p]) if (!V[a]) if (V[a] = 1; !D[a] || f(D[a])) return D[a] = p, 1; return 0; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); for (int n, m, r{}; cin >> n >> m, n && m; r = 0) { for (int i(1); i <= n; cin >> a[i++]); for (int i(1); i <= m; i++) { int k; cin >> k; for (int j(1); j <= n; j++) if (gcd(a[j], k) > 1) Gr[j].emplace_back(i); } for (int i(1); i <= n; r += f(i++)) memset(V, 0, sizeof V); cout << r << '\n'; for (int i(1); i < N; i++) Gr[i].clear(), D[i] = 0; } } | cs |
comment
끝
'Problem Solving > Baekjoon Online Judge (Platinum)' 카테고리의 다른 글
백준 28090 - 특별한 한붓그리기 (C++) (0) | 2023.05.31 |
---|---|
백준 17831 - 대기업 승범이네 (C++) (0) | 2023.05.22 |
백준 15060 - Imperial roads (C++) (1) | 2023.05.10 |
백준 23840 - 두 단계 최단 경로 4 (C++) (0) | 2023.05.09 |
백준 26262 - 트리 더하기 1 (C++) (0) | 2023.05.07 |