16126번: 동아리방 확장
첫 줄에 땅에 그려진 격자의 행 수와 열 수를 의미하는 정수 H, W(1 ≤ H, W ≤ 100)가 주어진다. 두 번째 줄부터 H줄에 걸쳐 각 줄에 0 이상 4 이하의 정수가 W개씩 주어진다. i번째 줄의 j번째 정수는
www.acmicpc.net
풀이:
https://rkm0959.tistory.com/124 처럼 2는 2개의 3과 연결되어야 하고, 3은 1개의 3 또는 1개의 2와 연결되어야 한다는 걸 플로우로 모델링하면 된다.
처음에는 에드몬드-카프를 썼는데 TLE가 나왔고, bipartite matching을 써서 통과했다.
푼 사람 중에서 속도가 가장 느린 축에 속하는데 플로우로 모델링한 점에 만족하고 넘어간다.
#include "prelude.h"
constexpr int INF = INT_MAX / 2;
constexpr int xs[4] = {-1, 0, 0, 1};
constexpr int ys[4] = {0, -1, 1, 0};
using namespace std;
using pii = pair<int, int>;
using pli = pair<long, int>;
using ll = long long;
class BipartiteMatching {
public:
BipartiteMatching(int N, int M) : graph(N), A(N, -1), B(M, -1), cnt(-1) {}
void addEdge(int from, int to) {
graph[from].push_back(to);
}
bool dfs(vector<bool>& visited, int cur) {
visited[cur] = true;
for (auto to : graph[cur]) {
if (B[to] == -1 || (!visited[B[to]] && dfs(visited, B[to]))) {
A[cur] = to;
B[to] = cur;
return true;
}
}
return false;
}
int count() {
if (cnt != -1) {
return cnt;
}
cnt = 0;
for (int i = 0; i < A.size(); ++i) {
if (A[i] == -1) {
vector<bool> visited(A.size(), false);
if (dfs(visited, i)) {
++cnt;
}
}
}
return cnt;
}
vector<vector<int>> graph;
vector<int> A;
vector<int> B;
int cnt;
};
int board[101][101];
int main() {
DEFIN2(N, M);
bool inval = false;
FOR(i, N) {
FOR(j, M) {
IN(board[i][j]);
if (board[i][j] < 2) {
inval = true;
}
}
}
if (inval) {
PRINTLN("HOMELESS");
return 0;
}
BipartiteMatching bm(N*M*2+2, N*M*2+2);
auto to = [&](int x, int y) { return (x * M + y) * 2; };
int totin = 0;
int totout = 0;
FOR(i, N) {
FOR(j, M) {
if ((i + j) % 2 == 0) {
if (board[i][j] == 4) {
continue;
}
totin += (board[i][j] == 3 ? 1 : 2);
for (int k = 0; k < 4; ++k) {
int ni = i + xs[k];
int nj = j + ys[k];
if (Board(ni, nj, N, M)) {
int f = board[i][j];
int t = board[ni][nj];
if (f == 2 && t == 3) {
bm.addEdge(to(i, j), to(ni, nj));
bm.addEdge(to(i, j) + 1, to(ni, nj));
} else if (f == 3 && t == 2) {
bm.addEdge(to(i, j), to(ni, nj));
bm.addEdge(to(i, j), to(ni, nj) + 1);
} else if (f == 3 && t == 3) {
bm.addEdge(to(i, j), to(ni, nj));
}
}
}
} else {
if (board[i][j] == 4) {
continue;
}
totout += (board[i][j] == 3 ? 1 : 2);
}
}
}
auto maxflow = bm.count();
if (maxflow == max(totin, totout)) {
PRINTLN("HAPPY");
} else {
PRINTLN("HOMELESS");
}
return 0;
}
'PS' 카테고리의 다른 글
백준 1741번 - 반 나누기 (0) | 2022.04.14 |
---|---|
PS용 개인 라이브러리 (0) | 2022.04.14 |