并查集+拓扑 hdu 1811 Rank of Tetris

hdu 1811 Rank of Tetris
//hdu 1811 Rank of Tetris

//并查集+拓扑



//思路:用并查集把相等的点归到一起,再用拓扑



//纠结这题纠结了一整天,看了n多的博客感觉这个不错

//http://972169909-qq-com.iteye.com/blog/1052820





#include <stdio.h>

#include <string.h>

#include <queue>



using namespace std;



#define comein freopen("in.txt", "r", stdin);

#define N 10005

#define M 20005

#define INF 1<<30

#define eps 1e-5



struct edge

{

    int win, lost, next;

}adja[M];



int  tot;   //记录插入邻接表的个数

int degree[N];

int win[M], lost[M], head[N], set[N];



int find(int root)

{

    if(root == set[root])

        return root;

    return set[root] = find(set[root]);

}



void add_edge(int r_a, int r_b)

{

    degree[r_b]++;

    adja[++tot].win = r_a;

    adja[tot].lost = r_b;

    adja[tot].next = head[r_a];

    head[r_a] = tot;

}



void topo(int n_node, int all)

{

    queue<int>que;

    bool uncer = false;

    for(int i = 0; i < n_node; ++i)//要集合根节点且度为0的才可入队,若只判断

        if(degree[i] == 0 && i == find(i))  //degree[find(i)]==0,可能会重复入队

            que.push(i);

    while(!que.empty())

    {

        if(que.size() > 1)

            uncer = true;

        int now = que.front();

        que.pop();

        all--;

        for(int i = head[now]; i != -1; i = adja[i].next)

        {

            if(--degree[ adja[i].lost ] == 0)

                que.push( adja[i].lost );

        }

    }

    if(all > 0) //剩下的集合数大于1,则存在环

        puts("CONFLICT");

    else if(uncer == true)

        puts("UNCERTAIN");

    else

        puts("OK");

}



int main()

{

    // comein

    int n_node, n_pair;

    while(scanf("%d%d", &n_node, &n_pair) == 2)

    {

        for(int i = 0; i <= n_node; ++i)    //初始化并查集

            set[i] = i;



        int cnt = 0, all = n_node;    //若相等的点看做一个点,cnt记录总的点数



        for(int i = 0; i < n_pair; ++i)

        {

            int wn, lt;

            char ra;

            scanf("%d %c %d", &wn, &ra, &lt);

            if(ra == '=')

            {   //这里要先求出来r_a和r_b,然后下面要用set[r_a] = r_b

                //或set[r_b] = r_a,也不知道为什么,一天下来都在找bug

                //无缘无故就被de掉了,提交了30几次,有的这里不用这样也可以ac

                //有的不能,快崩溃了

                int r_a = find(wn), r_b = find(lt);

                if(r_a != r_b)

                {

                    set[r_a] = r_b;

                    all--;

                }

            }

            else if(ra == '>')

            {

                win[++cnt] = wn;

                lost[cnt] = lt;

            }

            else

            {

                win[++cnt] = lt;

                lost[cnt] = wn;

            }

        }



        memset(adja, 0, (n_pair+5)*sizeof(edge));

        for(int i = 0; i < n_node; ++i)

        {

            head[i] = -1;

            degree[i] = 0;

        }

        tot = 0;

        bool flag = false;

        for(int i = 1; i <= cnt; ++i)

        {

            int r_a = find(win[i]), r_b = find(lost[i]);

            if(r_a == r_b)  //上面的已经把'='的情况合并起来了

            {           //这里都是处理不等的,如果出现相等的,说明冲突了

                flag = true;

                break;

            }

            add_edge(r_a, r_b);

        }

        if(flag == true)

        {

            puts("CONFLICT");

            continue;

        }

        topo(n_node, all);

    }

    return 0;

}

 

你可能感兴趣的:(rank)