zoukankan      html  css  js  c++  java
  • HDU 1811 Rank of Tetris 【拓扑排序 + 并查集】

    自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球。

    为了更好的符合那些爱好者的喜好,Lele又想了一个新点子:他将制作一个全球Tetris高手排行榜,定时更新,名堂要比福布斯富豪榜还响。关于如何排名,这个不用说都知道是根据Rating从高到低来排,如果两个人具有相同的Rating,那就按这几个人的RP从高到低来排。

    终于,Lele要开始行动了,对N个人进行排名。为了方便起见,每个人都已经被编号,分别从0到N-1,并且编号越大,RP就越高。
    同时Lele从狗仔队里取得一些(M个)关于Rating的信息。这些信息可能有三种情况,分别是"A > B","A = B","A < B",分别表示A的Rating高于B,等于B,小于B。

    现在Lele并不是让你来帮他制作这个高手榜,他只是想知道,根据这些信息是否能够确定出这个高手榜,是的话就输出"OK"。否则就请你判断出错的原因,到底是因为信息不完全(输出"UNCERTAIN"),还是因为这些信息中包含冲突(输出"CONFLICT")。
    注意,如果信息中同时包含冲突且信息不完全,就输出"CONFLICT"。
    Input
    本题目包含多组测试,请处理到文件结束。
    每组测试第一行包含两个整数N,M(0<=N<=10000,0<=M<=20000),分别表示要排名的人数以及得到的关系数。
    接下来有M行,分别表示这些关系
    Output
    对于每组测试,在一行里按题目要求输出
    Sample Input
    3 3
    0 > 1
    1 < 2
    0 > 2
    4 4
    1 = 2
    1 > 3
    2 > 0
    0 > 1
    3 3
    1 > 0
    1 > 2
    2 < 1
    Sample Output
    OK
    CONFLICT
    UNCERTAIN
    【分析】:
    1.合法输出OK
    2.有环,这里注意,可能有相等的情况,那么把相等的两个数合并,然后用他们的根作为代表当作点,合并一次,n的总数就-1
    3.不符合拓扑唯一性,那么压入队列时队列大小>1说明有不同的入度为0的点,那么标记一下

    【代码】:

    #include<cstdio>
    #include<string>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<set>
    #include<queue>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<cctype>
    #include<stack>
    #include<sstream>
    #include<list>
    #include<assert.h>
    #include<bitset>
    #include<numeric>
    #define debug() puts("++++")
    #define gcd(a,b) __gcd(a,b)
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define fi first
    #define se second
    #define pb push_back
    #define sqr(x) ((x)*(x))
    #define ms(a,b) memset(a,b,sizeof(a))
    #define sz size()
    #define be begin()
    #define pu push_up
    #define pd push_down
    #define cl clear()
    #define lowbit(x) -x&x
    #define all 1,n,1
    #define rep(i,n,x) for(int i=(x); i<(n); i++)
    #define in freopen("in.in","r",stdin)
    #define out freopen("out.out","w",stdout)
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair<int,int> P;
    const int INF = 0x3f3f3f3f;
    const LL LNF = 1e18;
    const int maxm = 1e6 + 10;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int dx[] = {-1,1,0,0,1,1,-1,-1};
    const int dy[] = {0,0,1,-1,1,-1,1,-1};
    const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    using namespace std;
    
    const int maxn = 10010;
    const int mod = 142857;
    
    int n,m,num;
    queue<int> q;
    vector<int> G[20010];
    char c[20010];
    int inDeg[10010],fa[10010];
    int a[20010],b[20010];
    
    void init()
    {
        for(int i=0;i<=n;i++)
        {
            fa[i]=i;
            G[i].clear();
        }
    }
    
    int Find(int x)
    {
        if(fa[x] == x) return x;
        return fa[x]=Find(fa[x]);
    }
    
    int join(int x,int y)
    {
        int fx=Find(x);
        int fy=Find(y);
        if(fx==fy) return 0;
        if(fx!=fy)
        {
            fa[fy]=fx;
        }
        return 1;
    }
    
    void topSort()
    {
        int ok=0;
        while(!q.empty()) q.pop();//
        for(int i=0; i<n; i++) if(!inDeg[i] && Find(i)==i) q.push(i); //入度为0且是根节点的时候才压入队列
        while(!q.empty())
        {
            if(q.size()>1) ok=1;
            int now = q.front(); q.pop();
            num--;
            for(int i=0;i<G[now].size();i++)
            {
                int nxt = G[now][i];
                if(--inDeg[nxt] == 0)
                {
                    q.push(nxt);
                }
            }
        }
        if(num>0) printf("CONFLICT
    ");
        else if(ok) printf("UNCERTAIN
    ");
        else  printf("OK
    ");
    }
    
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            init();
            memset(inDeg,0,sizeof(inDeg));
            num=n;
            for(int i=0;i<m;i++)
            {
                scanf("%d %c %d",&a[i],&c[i],&b[i]);
                if(c[i] == '=') //预处理相等的情况
                {
                    if(join(a[i],b[i])) //一直在这里WA掉却不知道,因为只有根节点不同才合并
                        num--;
                }
            }
            for(int i=0;i<m;i++)
            {
                if(c[i]=='=') continue;
                int x=Find(a[i]);
                int y=Find(b[i]);
                if(c[i] == '>')
                {
                    G[x].push_back(y);
                    inDeg[y]++;
                }
                if(c[i] == '<')
                {
                    G[y].push_back(x);
                    inDeg[x]++;
                }
            }
            topSort();
        }
    }
    
  • 相关阅读:
    Tjoi 2017 异或和
    Noi 十连测 建造记者站
    Noi 十连测 基因改造计划
    Noi 十连测 人生的经验
    NOI 十连测 Round 5 T2 运河计划
    NOI 十连测 Round 5 T1
    【ZJOI2018】迷宫
    BZOJ 十连测 day5 T3
    BZOJ 十连测 可持久化字符串
    BZOJ 十连测 二进制的世界
  • 原文地址:https://www.cnblogs.com/Roni-i/p/9181343.html
Copyright © 2011-2022 走看看