Rank of Tetris
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7126 Accepted Submission(s): 2016
Problem Description
自从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
下面的AC代码,百度网上人家的代码,加上自己的理解和注释,重新敲了遍。
觉得就是刚开始没转过来 。用并查集 处理掉等于的情况,剩下就是个简单的拓扑处理。
/*
HDU 1811 Rank of Tetris
http://acm.hdu.edu.cn/showproblem.php?pid=1811
*/
#include <stdio.h>
#include <iostream>
#include <queue>
#include <string.h>
using namespace std;
int n,m,sum;
vector<int> G[10001]; // 邻接表 G[i][j1] G[i][j2] 表示 i > j1 , i > j2
int in_degree[10001]; // 入度
int f[10001]; // 并查集f[]数组
int find(int x) // 并查集find
{
if(f[x]!=x)
f[x]=find(f[x]);
return f[x];
}
int judge(int a,int b) //用并查集判断是否已经相等,/ 没相等需要合并,同时计数的sum减1;
{
int aa = find(a);
int bb = find(b);
if(aa == bb)
return 0;
f[aa] = bb; // 合并
return 1;
}
void add(int x,int y) //邻接表添加 x > y ,x y是find处理后的结果
{
if(find(G[x].begin(), G[x].end(), y) == G[x].end()) // 添加的是不重复的
{
G[x].push_back(y);
in_degree[y] ++ ; // y入度加1
}
}
void tuopu() //拓扑排序
{
int i ,j ;
int t = 0;
queue<int> q; // 存储入度为0的点
int flag = 0;
for(i = 0 ; i < n; i ++)
{
if(in_degree[i] == 0 && find(i) == i)
{
q.push(i);
t++; //记录入度为0的点的个数
}
}
while( !q.empty() )
{
if(t > 1) // 至少两个元素 入度为0 他们的关系不确定
flag = 1 ;
int u = q.front();
q.pop();
t--;
sum -- ;
int len = G[u].size();
for(i = 0; i < len ;i ++)
{
in_degree[ G[u][i] ] -- ; // G[i][j] i出去后 j的入读要减去1 然后再判断
if(in_degree[ G[u][i] ] == 0)
{
q.push(G[u][i]);
t ++;
}
}
}
if(sum > 0) //sum > 0 说明出现了环 这个先判断 在判断关系是否明确 最后ok
cout << "CONFLICT" << endl;
else if(flag == 1)
cout << "UNCERTAIN" <<endl;
else
cout<<"OK"<<endl;
}
int main()
{
//freopen("in.txt","r",stdin);
while(cin >> n >> m)
{
int i , j , k ;
int x[20001] , y[20001]; // x c y 存储输入的内容
char ch[20001] ;
sum = n ; // sum 初始为节点的总个数 并查集处理的时候需要减
for(i = 0 ; i <= n ; i ++) // 并查集f初始化
{
f[i] = i;
G[i].clear(); //清空
in_degree[i] = 0 ; // 入度初始为0
}
// 输入 和 等于号用并查集处理
for(i = 0 ; i < m ; i ++)
{
cin >> x[i] >> ch[i] >> y[i] ;
if(ch[i] == '=')
if(judge(x[i] , y[i]))
sum --; // 个数减去1
}
// 大于,小于号 处理
for(i = 0 ; i < m ; i ++)
{
if(ch[i] == '=')
continue;
int aa = find(x[i]);
int bb = find(y[i]);
if(ch[i] == '>') // 用>处理
add(aa,bb);
else
add(bb,aa);
}
tuopu(); // 拓扑处理 打印结果
}
return 0;
}