【基础拓扑排序】poj 1094

本文深入探讨了一道经典的拓扑排序题目,着重解析了矛盾优先级问题的处理策略。通过实例分析,展示了如何在面对多个入度为0的节点时,不立即输出结果,而是等待后续可能的线段加入来确定唯一答案,从而避免误判。文中提供了详细的代码实现和优化思考,帮助读者理解并解决这类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这题很基础也很经典,不过个人认为有一个非常容易出错的地方,就是矛盾Inconsistency的优先级比不确定的优先级高,因为当前有矛盾就立即跳出,而当前有多个点入度为0就不能立即输出,有可能后来加入的线段可以确定唯一答案,就像下图一样。。。很阴险!wa了几次才得以ac。原本想用队列,但是不好搞


#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <limits.h>

using namespace std;

int lowbit(int t){return t&(-t);}
int countbit(int t){return (t==0)?0:(1+countbit(t&(t-1)));}
int gcd(int a,int b){return (b==0)?a:gcd(b,a%b);}
#define LL long long
#define PI acos(-1.0)
#define N  1000010
#define MAX INT_MAX
#define MIN INT_MIN
#define eps 1e-8
#define FRE freopen("a.txt","r",stdin)

int g[30][30];
string order;
int n,m;
int ans;
int in[30];
int vis[30];
queue<int> q;
int cnt[30];
int topsort(){
    int i,j,k;
    order.clear();
    memcpy(cnt,in,sizeof(cnt));
    int flag=0;
    for(i=1;i<=n;i++){
        int num=0,pos;
        for(j=1;j<=n;j++)
            if(cnt[j]==0)
               {pos=j;num++;}
        if(!num) return 0;
        if(num>1) flag=1;           //这里!!!不能立即跳出,因为后面接下来有可能矛盾
        cnt[pos]=-1;
        order+=pos-1+'A';
        for(j=1;j<=n;j++)
        if(g[pos][j])
        cnt[j]--;
    }
    if(flag)return 2;
    return 1;
}



/*
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            if(g[i][j]){
                in[j]++;
                vis[i]=1;
                vis[j]=1;
                }
    for(i=1;i<=n;i++)
        if(in[i]==0 && vis[i])
            q.push(i);

    if(q.size()==0) {return 0;}
    if(q.size()>1) {return 2;}

    while(!q.empty()){
        int x=q.front();
        q.pop();
        order+=(x+'A'-1);
        for(i=1;i<=n;i++){
            if(g[x][i])
                {
                    in[i]--;
                    if(in[i]==0)
                        q.push(i);
                }

        }
        if(q.size()>1)return 2;
    }
    if(order.size()==n) return 1;
    return 2;*/


int main(){
    while(scanf("%d%d",&n,&m) && (n+m)){
        int i,j,k;
        for(i=0;i<=n;i++)
            for(j=0;j<=n;j++)
                {g[i][j]=g[j][i]=0;in[i]=0;}

        int tag=0;
        char str[4];
        for(i=1;i<=m;i++){
            scanf("%s",str);
            if(tag)continue;
            int a=str[0]-'A'+1,b=str[2]-'A'+1;
            g[a][b]=1;
            in[b]++;
            ans=topsort();
            if(ans==0){
                printf("Inconsistency found after %d relations.\n",i);
                tag=1;
            }
            if(ans==1){
                printf("Sorted sequence determined after %d relations: ",i);
                cout<<order<<".\n";
                tag=1;
            }
        }
        if(!tag)
            puts("Sorted sequence cannot be determined.");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值