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, 
0 sizeof (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 ;
}