1. 程式人生 > >HDU 1811 Rank of Tetris(並查集+拓撲排序)

HDU 1811 Rank of Tetris(並查集+拓撲排序)

題意:給出n個點,m個關係。

  • u > v表示u的rating高於v的。
  • u < v表示u的rating低於v的。
  • u = v表示u的rating等於v的,則最後的排序按照標號大小來排。

問給定的關係,如果存在矛盾,輸出CONFLICT,如果存在不確定的,輸出UNCERTAIN;都沒有輸出OK

思路:不需要考慮相等的時候的大小關係,把相等的點都看作一個點(用並查集來縮成一個點),然後對縮點後的圖,跑一遍拓撲排序即可。
注意:當矛盾和不確定同時存在時,首先輸出矛盾。

程式碼:

#include <stdio.h>
#include <queue>
#include <string.h> #include <algorithm> #include <vector> #include <iostream> using namespace std; const int N = 1e4 + 10; vector<int> g[N], h[N]; char answer[3][20] = {"OK", "CONFLICT", "UNCERTAIN"}; int in[N], f[N]; bool vis[N]; // 記錄當前點是否還在縮點後的圖中 int n, m; int _find(int
x) { return f[x] = (f[x] == x ? x : _find(f[x])); } int tp_sort() { int ct = m, res = 0; queue<int> q; for (int i = 0; i < n; i++) { if (in[i] == 0 && vis[i]) { q.push(i); ct--; } } while (!q.empty()) { if (q.size() > 1) res = 2
; int u = q.front(); q.pop(); for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; in[v]--; if (in[v] == 0) { q.push(v); ct--; } } } if (ct > 0) return 1; return res; } void init() { int ct = 0; for (int i = 0; i < n; i++) { int fi = _find(i); if (fi != i) { ct++; vis[i] = false; } for (int j = 0; j < h[i].size(); j++) { int fj = _find(h[i][j]); g[fi].push_back(fj); in[fj]++; } } m = n - ct; } int main() { while (scanf("%d%d", &n, &m) != EOF) { for (int i = 0; i < n; i++) { h[i].clear(); g[i].clear(); } memset(in, 0, sizeof(in)); memset(vis, true, sizeof(vis)); for (int i = 0; i < n; i++) f[i] = i; for (int i = 0; i < m; i++) { int u, v; char o[2]; scanf("%d%s%d", &u, o, &v); int fu = _find(u); int fv = _find(v); if (o[0] == '<') { h[v].push_back(u); } else if (o[0] == '>') { h[u].push_back(v); } else if (o[0] == '=') { if (fu != fv) f[fu] = fv; } else { printf("Error\n"); } } init(); // 縮點,並轉換圖 int res = tp_sort(); printf("%s\n", answer[res]); } return 0; }