문제: icpc.me/2787
구간에 대한 최댓값과 최솟값이 주어질 때 valid한 수열을 만들 수 있는지 여부를 조사하고 가능할 경우 수열을 출력하는 문제이다.
우리는 구간에 대한 최댓값과 최솟값의 정보를 가지고 i번 위치에 올 수없는 값들을 전부 check해준 뒤 쿼리 입력이 끝나면
i번 위치에 올 수 있는 모든 값들을 연결하여 이분매칭을 시켜주면 된다.
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 | #include <cstdio> #include <algorithm> #include <vector> #include <cstring> #define MAX_N 200 using namespace std; vector<vector<int>> vt; int visited[MAX_N + 1], b[MAX_N + 1], n, m, x[MAX_N + 1][MAX_N + 1], r[MAX_N + 1]; 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; r[here] = there; return true; } } return false; } int bmatch() { int ret = 0; for (int i = 1; i <= n; i++) { memset(visited, 0, sizeof(visited)); if (dfs(i))ret++; } return ret == n; } int main() { scanf("%d%d", &n, &m); vt.resize(n + 1); for (int i = 1; i <= m; i++) { int f, q, w, e; scanf("%d%d%d%d", &f, &q, &w, &e); if (f == 1) { for (int j = q; j <= w; j++) { for (int k = e + 1; k <= n; k++) x[j][k] = 1; } } else { for (int j = q; j <= w; j++) { for (int k = 1; k < e; k++) x[j][k] = 1; } } for (int j = 1; j < q; j++)x[j][e] = 1; for (int j = w + 1; j <= n; j++)x[j][e] = 1; } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (!x[i][j])vt[i].push_back(j); } } if (!bmatch()) printf("-1"); else { for (int i = 1; i <= n; i++) { printf("%d ", r[i]); } } puts(""); return 0; } | cs |
'알고리즘 관련 > BOJ' 카테고리의 다른 글
BOJ)1966 프린터 큐 (0) | 2017.02.21 |
---|---|
BOJ)6064 카잉 달력 (0) | 2017.02.21 |
BOJ)2191 들쥐의 탈출 (0) | 2017.02.20 |
BOJ)9169 나는 9999번 문제를 풀 수 있다 (0) | 2017.02.20 |
BOJ)1017 소수 쌍 (0) | 2017.02.20 |