hdu 1811 拓扑排序+并查集

首先用并查集将“=”的元素合并成一个,然后用拓扑排序判断能否排序

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;


int fa[11000];
int N, M, cnt;
vector<int> vec[11000];
int in[11000];
int num1[21000], num2[21000];
char s[21000][3];

int finds( int x ){
    int temp = x;
    while( temp != fa[temp] ){
        temp = fa[temp];
    }
    while( x != temp ){
        int t = fa[x];
        fa[x] = temp;
        x = t;
    }
    return temp;
}

int links( int a, int b ){
    int f1 = finds( a );
    int f2 = finds( b );
    if( f1 != f2 ){
        fa[f1] = f2;
        return 1;
    }
    return 0;
}

void solve(){
    queue<int> q;
    while( !q.empty() ){
        q.pop();
    }
    for( int i = 0; i < N; i++ ){
        int t = finds( i );
        if( in[t] == 0 && fa[t] == i ){
            q.push( t );
        }
    }
    bool flag = false;
    while( !q.empty() ){
        if( q.size() != 1 ){
            flag = true;
        }
        int n = q.front();
        q.pop();
        cnt--;
        for( int i = 0; i < vec[n].size(); i++ ){
            in[vec[n][i]]--;
            if( in[vec[n][i]] == 0 ){
                q.push( vec[n][i] );
            }
        }
    }
    if( cnt > 0 ){
        printf( "CONFLICT\n" );
    }else if( flag ){
        printf( "UNCERTAIN\n" );
    }else{
        printf( "OK\n" );
    }
}

int main(){
    while( scanf( "%d%d", &N, &M ) != EOF ){
        cnt = N;
        for( int i = 0; i <= N; i++ ){
            vec[i].clear();
            fa[i] = i;
        }
        memset( in, 0, sizeof( in ) );

        bool flag = false;
        for( int i = 0; i < M; i++ ){
            scanf( "%d%s%d", &num1[i], s[i], &num2[i] );
            if( s[i][0] == '=' ){
                if( links( num1[i], num2[i] ) ){
                    cnt--;
                }
            }

        }
        for( int i = 0; i < M; i++ ){
            int f1 = finds( num1[i] );
            int f2 = finds( num2[i] );
            if( s[i][0] == '>' ){
                if( f1 == f2 ){
                    flag = true;
                }
                in[f2]++;
                vec[f1].push_back( f2 );
            }else if( s[i][0] == '<' ){
                if( f1 == f2 ){
                    flag = true;
                }
                in[f1]++;
                vec[f2].push_back( f1 );
            }
        }
        if( flag ){
            printf( "CONFLICT\n" );
            continue;
        }
        solve();
    }
    return 0;
}
/*
4 3
0 > 1
1 = 2
2 > 3
4 3
0 = 1
1 > 2
2 > 3
2 1
0 = 1
3 3
0 = 1
1 = 2
0 = 1
3 3
0 > 1
1 > 2
2 < 1
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值