hdu 1811
题目大意:
    有n个点,m个序关系,关系只有三种表示方式:a < b , a > b , a = b,问根据给定的关系能否将n个点排成有序,能输出OK,若两点之间出现 a < b 且 b < a 的情况,则输出CONFLICT,若出现某些点间的关系不确定,则输出UNCERTAIN,若后两者同时存在,则优先输出CONFLICT。
题目分析:
    由于存在 a = b 的情况,所以需要用并查集,将所有相等的点进行缩点,然后进行拓扑排序,注意!优先输出CONFLICT。

#include<stdio.h>
#include
<string.h>
#include
<vector>
#define N 10010
using namespace std;
vector
<int>g[N];
int rank[N], f[N], m,n,num[N], save[20005][2], q[N];
int find(int x)//并查集的查找函数
{
    
if(f[x]==x) return x;
    
else return f[x]=find(f[x]); //路径压缩,而且这样写对汇编源码有优化,不容易因递归层数太多出现栈溢出,但仅是不易!
}
void Union(int x, int y)//并查集的合并操作
{
    
int a=find(x);
    
int b=find(y);
    
if(a!=b){
        
if(rank[a]<rank[b])      //通过判断两个集合的大小,将小集合并入大集合,减少递归层数,算是个优化
            f[a]
=b, rank[b]+=rank[a];
        
else
            f[b]
=a, rank[a]+=rank[b];
    }
}
int main()
{
    
int i,j,k,a,b,ans,tmp,x,y,tim;
    
char s[5];
    
while(scanf("%d %d",&n,&m)!=EOF){
        
for(i=0; i<=n; i++){
            f[i]
=i;
            g[i].clear();
            rank[i]
=1;
        }
        memset(num, 
0sizeof(num));
        k
=0;
        
for(i=0; i<m; i++){
            scanf(
"%d %s %d",&a, s, &b);
            
if(s[0]!='='){
                
if(s[0]=='>'){
                    tmp
=a;
                    a
=b;
                    b
=tmp;
                }
                save[k][
0]=a, save[k++][1]=b;
            }
            
else if(s[0]=='='){
                Union(a, b);
            }
        }
        
for(i=0; i<k; i++){
            x
=find(save[i][0]);
            y
=find(save[i][1]);
            g[x].push_back(y);
            num[y]
++;
        }
        ans
=0;
        
int head=0, tail=0;             //从这里开始拓扑排序,用队列做保险啊,直接写的话很容易错
        k
=0;
        
for(i=0; i<n; i++)
            
if(num[i]==0 && find(i)==i){ //找到第一轮入度(num[])为零的点入队。
                q[tail
++]=i;
                k
++;
            }
        
if(k==0)
            ans
=2;
        
else{
            
if(k>1) ans=1;  //本题要求
            
while(head<tail){                    //排序过程
                x
=q[head++]; num[x]=-1; k=0;
                
for(i=0; i<g[x].size(); i++){
                    y
=g[x][i];
                    num[y]
--;
                    
if(num[y]==0)
                        q[tail
++]=y, k++;
                }
                
if(k>1) ans=1//本题要求
            }
            
for(i=0; i<n; i++//本题要求
                if(num[i]>0){
                    ans
=2;
                    
break;
                }
        }
        
if(ans==0)
            printf(
"OK\n");
        
else if(ans==1)
            printf(
"UNCERTAIN\n");
        
else if(ans==2)
            printf(
"CONFLICT\n");
    }

    
return 0;
}