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;
}