HDU-1181 Rank of Tetris(重写)拓扑排序+并查集
这题一个地方没注意,导致错了很多次,之后还一直没找到错误。
出问题的地方就是在第一轮找入度为零的节点的时候直接找的祖先节点,导致祖先节点多次入队~~~
代码如下:
#include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> #include <queue> using namespace std; int N, M, set[10005], pos, cc; int rec[10005][2]; char r[10005][5]; struct Edge { int no, next; }e[20005]; struct Node { int de, next; }p[10005]; int find(int x) { return set[x] = x == set[x] ? x : find(set[x]); } void merge(int a, int b) { set[a] = b; } void insert(int x, int y) { ++pos; e[pos].next = p[x].next; p[x].next = pos; // 先建立逻辑关系,再更新数据 e[pos].no = y; ++p[y].de; } void topology() { int uc = false, pos, count = 0; queue<int>q; for (int i = 0; i < N; ++i) { // cur = find(i); 这样写可能使得祖先节点多次入队!!!! if (p[i].de == 0 && set[i] == i) { q.push(i); } } if (q.size() > 1) { // 直接判定队列的大小是否为1既可,非常方便 uc = true; } while (!q.empty()) { ++count; // 统计取出的点的总个数 pos = q.front(); q.pop(); for (int i = p[pos].next; i != -1; i = e[i].next) { if(--p[e[i].no].de == 0) { // 每次在做过修改的点上考虑是否入队,这样能够避免单纯找度为零所带来的去重操作 q.push(e[i].no); } } if (q.size() > 1) { uc = true; } } if (count < N-cc) { puts("CONFLICT"); } else if (uc){ puts("UNCERTAIN"); } else { puts("OK"); } } int main() { int x, y; while (scanf("%d %d", &N, &M) != EOF) { pos = cc = 0; for (int i = 0; i < N; ++i) { p[i].de = 0; p[i].next = -1; set[i] = i; } for (int i = 1; i <= M; ++i) { scanf("%d %s %d", &rec[i][0], r[i], &rec[i][1]); if (r[i][0] == '=') { int a = find(rec[i][0]), b = find(rec[i][1]); if (a != b) { ++cc; merge(a, b); } } } for (int i = 1; i <= M; ++i) { x = find(rec[i][0]), y = find(rec[i][1]); switch (r[i][0]) { case '<': { insert(x, y); break; } case '>': { insert(y, x); break; } } } topology(); } return 0; }