HDU 1811 Rank of Tetris

来源:互联网 发布:html5 javascript exe 编辑:程序博客网 时间:2024/05/20 15:39

题意:
(中文)
思路:
把所有得分相同的选手放到同一个集合里面,然后对这些结合的关系进行拓扑排序,看是否可以存在一个完全的有向无环图。
1.利用并查集合并集合。
2.利用队列进行拓扑排序,如果队列里面的元素个数超过1个了,那么就说明此时信息缺失(因为这些队列里面的参赛选手都没有比它们大的了,他们之间的相互关系无法确定),如果最后入队的个数小于集合的个数,说明在图中有环,就是冲突了(因为环里面没有任何一个点的入度为0)
Code:

#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<algorithm>#include<iostream>#include<string>#include<vector>#include<bitset>#include<queue>#include<stack>#include<list>#include<map>#include<set>#define TEST#define LL long long#define Mt(f, x) memset(f, x, sizeof(f));#define rep(i, s, e) for(int i = (s); i <= (e); ++i)#ifdef TEST    #define See(a) cout << #a << " = " << a << endl;    #define See2(a, b) cout << #a << " = " << a << ' ' << #b << " = " << b << endl;    #define debug(a, s, e) rep(_i, s, e) {cout << a[_i] << ' ';} cout << endl;    #define debug2(a, s, e, ss, ee) rep(i_, s, e) {debug(a[i_], ss, ee)}#else    #define See(a)    #define See2(a, b)    #define debug(a, s, e)    #define debug2(a, s, e, ss, ee)#endif // TESTconst int MAX = 2e9;const int MIN = -2e9;const double eps = 1e-8;const double PI = acos(-1.0);using namespace std;const int N = 20000 + 5;char op[N][2];int a[N], b[N];int uf[N], in[N];vector<int> vec[N];void init(int n){    for(int i = 0; i < n; ++i)    {        uf[i] = i;        vec[i].clear();    }    Mt(in, 0);}int fd(int n){    if(uf[n] != n)    {        uf[n] = fd(uf[n]);    }    return uf[n];}void unionSet(int a, int b){    int f1 = fd(a), f2 = fd(b);    if(f1 != f2)        uf[f1] = uf[f2];}int bfs(int n, int tem, bool &flag){    queue<int> Q;    for(int i = 0; i < n; ++i)    {        if(!in[i] && fd(i) == i)//选择所有入读为0的根(合法情况下只有一个)        {            Q.push(fd(i));        }    }    while(!Q.empty())    {        if(Q.size() > 1) flag = true;        int st = Q.front(); Q.pop();        tem--;        for(int i = 0; i < vec[st].size(); ++i)        {            const int &to = vec[st][i];            if(--in[to] == 0)//把通过此点连接的所有入读都减一,并找到这里面入度为0的点            {                Q.push(to);            }        }    }    return tem;}int main(){    int n, m;    while(~scanf("%d%d", &n, &m))    {        init(n);        int num = n;//最开始假设结合个数为n        for(int i = 0; i < m; ++i)        {            scanf("%d%s%d",  &a[i], op[i], &b[i]);            if(op[i][0] == '=')            {                unionSet(a[i], b[i]);                num--;//合并集合时,集合个数减1            }        }        bool clash = false;        for(int i = 0; i < m; ++i)        {            if(op[i][0] == '=') continue;            int fa = fd(a[i]), fb = fd(b[i]);            if(fa == fb)//找到各自的集合,看是否是同一个集合里面的            {                clash = true;                break;            }            if(op[i][0] == '<')            {                vec[fa].push_back(fb);                in[fb]++;            }            else            {                vec[fb].push_back(fa);                in[fa]++;            }        }        if(clash)        {            printf("CONFLICT\n");            continue;        }        bool flag = false;        int tem = bfs(n, num, flag);//拓扑排序 flag记录是否是信息不全,返回还没有入队的集合个数        if(tem > 0)        {            printf("CONFLICT\n");        }        else if(flag)        {            printf("UNCERTAIN\n");        }        else        {            printf("OK\n");        }    }    return 0;}
0 0
原创粉丝点击