문제: icpc.me/1017
N개의 수가 주어질 때 주어진 모든 수를 짝을 지을 때 모든 각각의 짝의 합이 소수가 되도록 할 때 첫 번째 수와 매칭 될 수 있는 모든 수를 구하는 문제이다.
어떤 수 a와 b가 서로 다를 경우 a+b가 소수가 되기 위해서는 a와 b가 짝수와 홀수로 나누어져야한다.
즉 우리는 짝수와 홀수로 이분 그래프 형태로 그래프를 모델링 해준 후 이분 매칭을 구해주어 n/2만큼 매칭 될 경우 1번 정점과 매칭 된 정점을 역추적 해주어 답에 넣어준 후 그 간선만 제거하고 다시 이분매칭을 실행함을 반복해주면 된다.
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | #include <cstdio> #include <algorithm> #include <vector> #include <cstring> using namespace std; bool p[3000], no[3000]; int n, visited[100], b[100], a[100]; vector<vector<int>> vt; vector<int> res; bool dfs(int here) { if (visited[here])return false; visited[here] = true; for (int there : vt[here]) { if (!b[there] || dfs(b[there])) { b[there] = here; return true; } } return false; } int bmatch() { memset(b, 0, sizeof(b)); int c = 0; for (int i = 1; i <= n; i++) { if (a[i] % 2 != a[1] % 2) continue; memset(visited, 0, sizeof(visited)); if (dfs(i))c++; } if (c == n / 2) { for (int i = 1; i <= n; i++) { if (b[i] == 1) { return a[i]; } } return 0; } else return 0; } int main() { p[0] = p[1] = true; for (int i = 2; i < 3000; i++) { if (p[i])continue; for (int j = i + i; j < 3000; j += i) p[j] = true; } scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); while (1) { vt.clear(); vt.resize(n + 1); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (i == j)continue; if (i == 1 && no[a[j]])continue; if (!p[a[i] + a[j]]) vt[i].push_back(j); } } int k = bmatch(); if (k) { res.push_back(k); no[k] = true; } else break; } sort(res.begin(), res.end()); if (!res.size()) res.push_back(-1); for (auto r : res) printf("%d ", r); puts(""); return 0; } | cs |
'알고리즘 관련 > BOJ' 카테고리의 다른 글
BOJ)2191 들쥐의 탈출 (0) | 2017.02.20 |
---|---|
BOJ)9169 나는 9999번 문제를 풀 수 있다 (0) | 2017.02.20 |
BOJ)13560 Football (0) | 2017.02.20 |
BOJ)12019 동아리방 청소! (0) | 2017.02.17 |
BOJ)1671 상어의 저녁식사 (0) | 2017.02.16 |