hdu1811 并查集+拓扑序

题意:现在有一个排名系统,有一系列信息,分别是 > < = 的比较,而如果最终相等,就会将这些相等的按照序号从小到大排,问给出的信息是否可以确定完整的排序。

由于如果很多点相等,他们肯定能够确定名次,那么我们只要让他们共同拥有与其他点的大小关系就行了。所以就用到了并查集,将相等的点加入并查集,再对并查集排拓扑序,如果能够排出唯一的拓扑序,那么在每个并查集内部也能够有唯一的顺序。

 #include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=1e4+;
const int maxm=2e4+; int fa[maxn],num,n;
int a[maxm],b[maxm];
char c[maxm][];
int head[maxn],point[maxm],nxt[maxm],size;
int id[maxn]; void init(){for(int i=;i<n;++i)fa[i]=i;} int find(int x){
int r=x,t;
while(r!=fa[r])r=fa[r];
while(x!=r){
t=fa[x];
fa[x]=r;
x=t;
}
return r;
} int topo(){
queue<int>q;
bool f=;
for(int i=;i<n;++i)if(fa[i]==i&&!id[i])q.push(i);
int cnt=;
while(!q.empty()){
int u=q.front();
q.pop();
cnt++;
if(!q.empty())f=;
for(int i=head[u];~i;i=nxt[i]){
int j=point[i];
id[j]--;
if(!id[j])q.push(j);
}
}
if(cnt!=num)return ;
if(f)return ;
return -;
} void add(int a,int b){
point[size]=b;
nxt[size]=head[a];
head[a]=size++;
id[b]++;
} int main(){
int m;
while(scanf("%d%d",&n,&m)!=EOF){
memset(id,,sizeof(id));
memset(head,-,sizeof(head));
size=;
init();
num=n;
for(int i=;i<=m;++i){
scanf("%d%s%d",&a[i],c[i],&b[i]);
if(c[i][]=='='){
int x=find(a[i]),y=find(b[i]);
if(x!=y){
fa[x]=y;
num--;
}
}
}
for(int i=;i<=m;++i){
if(c[i][]=='>'){
add(find(a[i]),find(b[i]));
}
else if(c[i][]=='<'){
add(find(b[i]),find(a[i]));
}
}
int tmp=topo();
if(tmp==)printf("OK\n");
else if(tmp==)printf("CONFLICT\n");
else if(tmp==-)printf("UNCERTAIN\n");
}
}
上一篇:js省市二级联动实例


下一篇:linux hdparm's -y 和 -Y 的区别