【HDOJ1811】【并查集预处理+拓扑排序】

http://acm.hdu.edu.cn/showproblem.php?pid=1811

Rank of Tetris

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 11382    Accepted Submission(s): 3261

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
题目大意:给一堆点的关系【大于小于或等于】让判断这些点之间的关系是否明确【任何两个点的关系都能确定】且正确【不会出现冲突】
题目分析:首先预处理:大于和小于容易处理,直接当作有向边就行,而等于应用并查集进行预处理使等于的关系点缩成连通块【这和强连通分量Tarjan缩点类似】,
     预处理完之后将各连通块按照关系进行有向连接,
     最后根据入度、出度以及拓扑序列中点的个数来确定是否正确。
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
queue<int>pq;
struct edge{
int to;
int next;
}EDGE[];
struct pot{
int to1;
int to2;
char ch;
}POT[];
int cnt=;
int flag;
int in[],head[],pre[],vis[],vviss[],vvis[],out[];
int n,m,N;
void add(int x,int y)
{
in[y]++;
out[x]++;
EDGE[cnt].to=y;
EDGE[cnt].next=head[x];
head[x]=cnt++;
}
int orz1=,orz2=;
int find(int x)
{
int xx=x;
while(x!=pre[x])
{
x=pre[x];
}
while(pre[xx]!=x)
{
int t=pre[xx];
pre[xx]=x;
xx=t;
}
return x;
}
void Topsort()
{
int wqw=;
for(int i = ; i < N ; i++)
{
if(!in[find(i)]&&!vis[find(i)])
{
wqw++;
orz2++;
vis[find(i)]=;
pq.push(find(i));
}
}
if(wqw>)flag=;
while(!pq.empty())
{
int qwq=pq.front();pq.pop();
for(int i = head[qwq];i != - ; i=EDGE[i].next)
{
int v=EDGE[i].to;
in[v]--;
if(!in[v])
{
orz2++;
pq.push(v);
}
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)==)
{
N=n;
orz1=;orz2=;
memset(head,-,sizeof(head));
memset(vis,,sizeof(vis));
memset(vvis,,sizeof(vvis));
memset(vviss,,sizeof(vviss));
memset(in,,sizeof(in));
memset(out,,sizeof(out));
for(int i = ; i < n ; i++)pre[i]=i;
for(int i = ; i < m; i++)
{
int a,c;
char b;
scanf("%d %c %d",&POT[i].to1,&POT[i].ch,&POT[i].to2);
if(POT[i].ch=='=')
{
if(find(POT[i].to1)!=find(POT[i].to2))
{
pre[find(POT[i].to1)]=find(POT[i].to2);
n--;
}
// vviss[find(POT[i].to2)]=1;
}
}
flag=;
for(int i = ; i < m ; i++)
{
if(POT[i].ch=='=')
continue;
char b=POT[i].ch;
int a=find(POT[i].to1);
int c=find(POT[i].to2);
if(a!=c)
{
if(b=='>')
add(a,c);
else if(b=='<')
add(c,a); }
else
flag=;
}
int qwq=;
if(flag!=)
{
for(int i = ; i < N ; i++)
{
if(!out[find(i)]&&!vvis[find(i)])
{
vvis[find(i)]=;
qwq++;
if(qwq>){
flag=;
break;}
}
}
Topsort();
if(orz2<n)flag=;
}
if(flag==)printf("UNCERTAIN\n");
else if(flag==)printf("CONFLICT\n");
else printf("OK\n");
} return ;
}
上一篇:java知识 特殊符号转换


下一篇:微信小程序教学第三章第三节(含视频):小程序中级实战教程:视图与数据关联