【1】HDU 1811(拓扑排序+并查集)

本文介绍了一种使用拓扑排序与并查集解决排名问题的方法。通过将相等关系的人群归并,并对每个集合的根节点进行拓扑排序来判断是否能得出唯一的排名顺序。如果出现多种排序可能性则输出不确定,若存在冲突则输出冲突。


题意:对N个人进行排名,给定两个人A、B,A>B  A=B  A<B。如果能得到唯一确定的排名输出OK,如果信息不完全输出UNCERTAIN如果有冲突输出CONFLICT

做法:将等于关系的放入一个集合中,对每个集合的根进行拓扑排序,发现有多种排序结果为UNCERTAIN 有环为CONFLICT

#include<stdio.h>

#include<string.h>

#include<queue>

#include<vector>

#include<iostream>

using namespace std;

const int maxn=10005;

const int maxm=20005;

intn,m,f[maxn],x[maxm],y[maxm],son[maxn];

char ope[maxm];

vector<int> g[maxn];

 

void initSet(int n)

{

    for(inti=0;i<=n;i++)f[i]=i;

    for(inti=0;i<=n;i++)g[i].clear();

    memset(son,0,sizeof(son));

}

int find(int x)

{

    returnx==f[x]?f[x]:f[x]=find(f[x]);

}

bool Union(int x,int y)

{

    inta=find(x),b=find(y);

    if(a==b)return false;

    if(a>b)f[b]=a;

    else

    {

 

        f[a]=b;

    }

    return true;

}

int main()

{

    while(scanf("%d %d",&n,&m)!=EOF)

    {

        initSet(n);

        int num=n;

        for(inti=0;i<m;i++)

        {

           scanf("%d %c %d",&x[i],&ope[i],&y[i]);

           if(ope[i]=='=')

           {

               if(Union(x[i],y[i]))num--;

           }

        }

        for(inti=0;i<m;i++)

        {

           if(ope[i]!='=')

           {

               intxx=find(x[i]),yy=find(y[i]);

               if(ope[i]=='>')

               {

                   g[xx].push_back(yy);

                   son[yy]++;

               }

               else

               {

                   g[yy].push_back(xx);

                   son[xx]++;

               }

           }

        }

        queue<int> q;

        for(inti=0;i<n;i++)

        {

           if(son[i]==0&&i==find(i))q.push(i);

        }

        int stan=0;

        while(!q.empty())

        {

           if(q.size()>1)stan=1;

           int t=q.front();

           q.pop();

           --num;

           for(int v=0;v<g[t].size();++v)

           {

               if(--son[g[t][v]]==0)q.push(g[t][v]);

           }

        }

    //  cout<<"?????????"<<endl;

        if(num>0)cout<<"CONFLICT"<<endl;

        else if(stan==1)cout<<"UNCERTAIN"<<endl;

        else cout<<"OK"<<endl;

    }

    return 0;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值