hdu1811_并查集+拓扑排序

题目大意:有n个点(编号0~n-1),有m个关系,“>”、“<”或者“=”。若这n个点能形成固定的链式大小关系,就输出”OK”,如果关系有冲突,则输出”CONFLICT”,如果关系不全,则输出”UNCERTAIN”。PS:坑点,”CONFLICT”优先于”UNCERTAIN”,所以判断到”UNCERTAIN”条件时,别急着输出”UNCERTAIN”,而是置一个”UNCERTAIN”的flag,等到最后先判断”CONFLICT”的条件,再判断”UNCERTAIN”的条件。

将有“=”关系的点merge在一起,作为一个点,然后进行拓扑排序

#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;
const int maxn = 10010;
const int maxm = 20010;
int head[maxn];
int to[maxm], nxt[maxm], tot;
int fa[maxn], in[maxm];
bool vis[maxn];
int n, m;

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

void merge_(int u, int v)
{
    int f1 = findfa(u);
    int f2 = findfa(v);
    if(f1 != f2) fa[f2] = f1;
}

void addedge(int u, int v)
{
    ++tot;
    to[tot] = v;
    nxt[tot] = head[u];
    head[u] = tot;
    ++in[v];
}

int topo_solve(int sum)
{
    queue <int> q;
    for(int i = 0; i < n; ++i)
    {
        int f = findfa(i);
        if(!in[f] && fa[f]==i) q.push(f);
    }
    bool flag = 0;
    while(!q.empty())
    {
        int tmp = q.front();
        q.pop();
        --sum;
        if(!q.empty()) flag = 1;//优先判断冲突!!!
        for(int i = head[tmp]; ~i; i = nxt[i])
        {
            --in[to[i]];
            if(!in[to[i]]) q.push(to[i]);
        }
    }
    if(sum > 0) return 0;
    if(flag) return 2;
    return 1;
}

int main()
{
    while(~scanf("%d %d", &n, &m))
    {
        for(int i = 0; i <= n; ++i)
        {
            fa[i] = i;
            head[i] = -1;
            in[i] = 0;
        }
        tot = 0;
        int sum = n;
        int u[maxm], v[maxm];
        char ch[maxm];
        for(int i = 0; i < m ; ++i)
        {
            scanf("%d %c %d", &u[i], &ch[i], &v[i]);
            if(ch[i]=='=')
            {
                --sum;
                merge_(u[i], v[i]);
            }
        }
        bool flag = 0;
        for(int i = 0; i < m; ++i)
        {
            if(ch[i]=='=') continue;
            int f1 = findfa(u[i]);
            int f2 = findfa(v[i]);
            if(f1 == f2)
            {
                flag = 1;
                printf("CONFLICT\n");
                break;
            }
            if(ch[i]=='<') addedge(f2, f1);
            else addedge(f1, f2);
        }
        if(flag) continue;
        int tag = topo_solve(sum);
        if(!tag) printf("CONFLICT\n");
        else if(tag==1) printf("OK\n");
        else printf("UNCERTAIN\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jay__bryant/article/details/80766713