hdu 1811 Rank of Tetris 并查集+拓扑排序

来源:互联网 发布:分类汇总数据复制出来 编辑:程序博客网 时间:2024/06/06 05:20

题意:给出一系列排名的信息,问你是否能确定排名,还是信息有冲突,或者信息不足。

这种确定先后顺序的题目我们很自然就能想到拓扑排序,拓扑排序时就可以判出是否冲突或信息不足,冲突就是有回路,信息不足就是在确定某个是谁时有多种选择,也就是在拓扑排序时入度为0的有多个。

代码如下,代码写的比较没有条理,因为之前拓扑排序用到时dfs版的,但后面想到这道题要有唯一的拓扑序列,所以应该用入度版。转换为入度后,问题变得容易了很多。所以以后写题时还是要先考虑清楚再敲代码。

#include <iostream>#include <string>#include <algorithm>#include <list>using namespace std;const int MAXN = 10000;const int MAXE = 20000;const int NIL = -1;const int INF = 0x3f3f3f3f;struct Edge {    int to, next;} edge[MAXE];struct Data {    int u, v;} dat[MAXE];int parent[MAXN];bool flag;int cnt, head[MAXN];int indegree[MAXN];enum Color{    WHITE, GRAY, BLACK} color[MAXN];int find_parent(int x){    return x == parent[x] ? x : parent[x] = find_parent(parent[x]);}inline void Union(int a, int b)    //a小b大{    int pa = find_parent(a);    int pb = find_parent(b);    if (pa != pb)        parent[pa] = pb;}inline void init(int n){    cnt = 0;    for (int i = 0; i < n; ++i)        parent[i] = i, head[i] = edge[i].next = NIL, color[i] = WHITE, indegree[i] = 0;}inline void add(int u, int v){    edge[cnt].to = v;    edge[cnt].next = head[u];    head[u] = cnt++;}int vertex[MAXN];int vertex_num;int main(void){    int M, N;    int u, v;    char temp[10];    while (scanf("%d %d", &N, &M) != EOF)    {        if (N == 0)        {            puts("OK");            continue;        }        if (M == 0 && N == 1)        {            puts("OK");            continue;        }        if (M == 0)        {            puts("UNCERTAIN");            continue;        }        init(N);        int id = 0;        while (M--)        {            scanf("%d %s %d", &u, temp, &v);            if (temp[0] == '=')            {                Union(min(u, v), max(u, v));                continue;            }            if (temp[0] == '<')                swap(u, v);            dat[id].u = u;            dat[id++].v = v;        }        flag = false;        for (int i = 0; i < id; ++i)        {            u = dat[i].u;            v = dat[i].v;            //u->parent[v]            int pu = find_parent(u);            int pv = find_parent(v);            if (pu == pv)            {                flag = true;    //CONFLICT                break;            }            add(pu, pv);            ++indegree[pv];        }        if (flag)        {            puts("CONFLICT");            continue;        }        vertex_num = 0;        for (int i = 0; i < N; ++i)            if (parent[i] == i)                vertex[vertex_num++] = i;        bool flag2 = false;        for (int i = 0; i < vertex_num; ++i)    //如果一次一个,那么n次就行        {            //找一个入度为零的点            int v = NIL;            int num = 0;            for (int j = 0; j < vertex_num; ++j)            {                u = vertex[j];                if (color[u] == WHITE && indegree[u] == 0)                {                    ++num;                    v = u;                }            }            if (v == NIL)            {                flag = true;                break;            }            if (num > 1)                flag2 = true;            color[v] = BLACK;            for (int i = head[v]; i != NIL; i = edge[i].next)            {                u = edge[i].to;                if (color[u] == WHITE)                    --indegree[u];            }        }        if (flag)            puts("CONFLICT");        else if (flag2)            puts("UNCERTAIN");        else            puts("OK");    }    return 0;}