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

給你一些編號的大小關係,問你能否對所有的編號排出大小順序,如果能輸出OK,如果給出的關係自相矛盾輸出CONFLICT,如果信息不全輸出UNCERTAIN. 如果僅有大於小於的話: 對於一種關係建立有向圖,然後進行拓撲排序,每次入度爲0的點入隊,如果隊中大於一個點,說明這些點之間沒有邊,即這些點不能判斷大小,信息不全。如果發現有環,說明衝突。
加上等於關係,如果還像原來一樣,一個數等於另一個數,那樣需要找到另一個數和其他數的大小關係,然後用這個數建邊,這樣就會非常麻煩,這裏我們把所有的相等的點選出一個點來代替他們(即並查集),點的總數相應減少就可以了

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;
#define maxn 11000
#define maxm 21000
int n,m;
int head[maxn],pre[maxn],indeg[maxn],vis[maxn];
char s[maxm];
int a[maxm],b[maxm];
int tot;
struct Edge
{
    int to,next;
} edge[maxm];
int findroot(int num)
{
    while(pre[num] != num)
    {
        num = pre[num];
    }
    return pre[num];
}
void add(int u,int v)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
    indeg[v]++;
}
int topo()
{
    queue<int>q;
    int ans = 1;
    int num = 0;
    int block = 0;
    for(int i = 0; i < n; i++)
    {
        if(findroot(i) == i)
        {
            block++;
        }
    }
    for(int i = 0; i < n; i++)
    {
        int temp = findroot(i);
        if(indeg[temp] == 0 &&vis[temp] == 0)
        {
            q.push(temp);
            vis[temp] = 1;
        }
    }
    while(!q.empty())
    {
        if(q.size() >= 2)
        {
            ans = -1;
        }
        int temp = q.front();
        q.pop();
        num++;
        for(int i = head[temp]; i != -1; i = edge[i].next)
        {
            int x = findroot(edge[i].to);
            indeg[x]--;
            if(indeg[x] == 0 && vis[x] == 0)
            {
                q.push(x);
                vis[x] = 1;
            }
        }
    }
    if(num < block) ans = 0;//衝突
    return ans;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        tot = 0;
        int ans = 4;
        memset(head,-1,sizeof(head));
        memset(indeg,0,sizeof(indeg));
        memset(vis,0,sizeof(vis));
        for(int i = 0; i < n; i++)
        {
            pre[i] = i;
        }
        for(int i = 0; i < m; i++)
        {
            scanf("%d %c%d",&a[i],&s[i],&b[i]);
            if(s[i] == '=')
            {
                int roota = findroot(a[i]);
                int rootb = findroot(b[i]);
                if(roota != rootb)
                {
                    pre[roota] = rootb;
                }
            }
        }
        for(int i = 0; i < m; i++)
        {
            int u = findroot(a[i]), v = findroot(b[i]);
            if(u == v && s[i] != '=')
            {
                ans = 0;
                break;
            }
            if(s[i] == '<') add(u,v);
            if(s[i] == '>') add(v,u);
        }
        if(ans != 0)
            ans = topo();
        if(ans == 1) printf("OK\n");
        if(ans == -1) printf("UNCERTAIN\n");
        if(ans == 0) printf("CONFLICT\n");
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章