문제:icpc.me/3665
작년의 등수가 주어지고 올해 등수가 역전 된 두 팀의 목록이 주어질 때 올해 순위를 발표하는 문제이다.
우선 작년의 등수를 기반으로 n^2의 방법으로 간선을 연결해주고 올해에 뒤 바뀐 순위를 기반으로 간선의 방향을 바꿔준다.
이후 위상정렬을 해주면 되는데 이 때 큐에 동시에 2개가 들어간다면 ?를 출력하고 n번을 돌리기전에 큐가 비어버린다면 사이클이 생긴것이므로 IMPOSSIBLE을 출력 해 주면 된다.
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 | #include <cstdio> #include <algorithm> #include <queue> #include <cstring> using namespace std; int t, n, m, a[501][501], in[501], x, y, b[500], r[500]; int main() { scanf("%d", &t); while (t--) { int f = 0; memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); memset(in, 0, sizeof(in)); scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &b[i]); for (int i = 0; i < n; i++) { for (int j = 0; j < i; j++) { a[b[j]][b[i]] = 1; in[b[i]]++; } } scanf("%d", &m); while (m--) { scanf("%d%d", &x, &y); if (a[x][y]) { in[y]--; in[x]++; } else { in[y]++; in[x]--; } swap(a[x][y], a[y][x]); } queue<int> qu; for (int i = 1; i <= n; i++) { if (!in[i]) qu.push(i); } for (int i = 0; i < n; i++) { if (qu.empty()) { f = 1; break; } else if (qu.size() > 1) { f = 2; break; } int here = qu.front(); r[i] = here; qu.pop(); for (int j = 1; j <= n; j++) { if (a[here][j]) { in[j]--; if (!in[j]) qu.push(j); } } } if (f == 1) printf("IMPOSSIBLE\n"); else if (f == 2) printf("?\n"); else { for (int i = 0; i < n; i++) printf("%d ", r[i]); printf("\n"); } } return 0; } | cs |
'알고리즘 관련 > BOJ' 카테고리의 다른 글
BOJ)3977 축구 전술 (0) | 2017.01.24 |
---|---|
BOJ)4196 도미노 (0) | 2017.01.24 |
BOJ)2637 장난감조립 (0) | 2017.01.22 |
BOJ)9470 Strahler 순서 (0) | 2017.01.22 |
BOJ)13711 LCS4 (0) | 2017.01.22 |