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

中文码题

对于等号的情况,用并查集合并(因为编号不同一定可以分出先后)

然后判断能否构成拓扑排序,以及拓扑排序是不是唯一的

题不难,考验代码能力,能1A证明手感还不错

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#include <queue>
#include <cmath>
#include <stack>
#include <set>

using namespace std;

int vis[10005],head[10005],cnt,fa[10005],st[10005];

struct p{
    int a,b;
    char op[5];
}kk[10005];

struct node{
    int s,t,nxt;
}e[1000005];

void add(int s,int t){
    e[cnt].s=s;e[cnt].t=t;e[cnt].nxt=head[s];head[s]=cnt++;
}

void INIT(){
    cnt=0;
    memset(head,-1,sizeof(head));
}

int find(int x){
    return fa[x]==x?x:fa[x]=find(fa[x]);
}


int dfs(int u){
    vis[u]=-1;
    for(int i=head[u];i!=-1;i=e[i].nxt){
        int v=e[i].t;
        if(vis[v]<0)return 0;
        else if(!vis[v] && !dfs(v))return 0;
    }
    vis[u]=1;
    return 1;
}

int OK(int n){
    for(int i=0;i<n;i++){
        if(!vis[i] && !st[i] && !dfs(i))return 0;
    }
    return 1;
}

int IN[10005];

int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        INIT();
        for(int i=0;i<n;i++)fa[i]=i;
        memset(IN,0,sizeof(IN));
        memset(st,0,sizeof(st));
        int flag=1;
        for(int i=0;i<m;i++){
            scanf("%d%s%d",&kk[i].a,kk[i].op,&kk[i].b);
            if(kk[i].op[0]=='='){
                int pa=find(kk[i].a);
                int pb=find(kk[i].b);
                if(pa!=pb){
                    fa[pa]=pb;
                    st[pa]=1;
                }
            }
            else{
                int pa=find(kk[i].a);
                int pb=find(kk[i].b);    
                if(pa==pb)flag=0;
            }
        }
        if(!flag)puts("CONFLICT");//所给信息矛盾 
        else{
            for(int i=0;i<m;i++){
                if(kk[i].op[0]=='>'){
                    add(find(kk[i].a),find(kk[i].b));
                    IN[find(kk[i].b)]++;
                }
                else if(kk[i].op[0]=='<'){
                    add(find(kk[i].b),find(kk[i].a));
                    IN[find(kk[i].a)]++;
                }
            }
            memset(vis,0,sizeof(vis));
            if(!OK(n))puts("CONFLICT");//有环 
            else{
                queue <int> q;
                for(int i=0;i<n;i++){
                    if(!st[i] && !IN[i])
                        q.push(i);
                }
                int flag=1;
                while(!q.empty()){
                    if(q.size()>1){
                        flag=0;
                        break;
                    }
                    int u=q.front();
                    q.pop();
                    for(int i=head[u];i!=-1;i=e[i].nxt){
                        int v=e[i].t;
                        IN[v]--;
                        if(!IN[v])q.push(v);
                    }
                }
                if(!flag)puts("UNCERTAIN");//拓扑结构一层多于一个点,有多种情况 
                else puts("OK");
            }
        }
    }
    return 0;
}
View Code