拓扑排序 附POJ 1094 Sorting It All Out 解题报告

       拓扑排序是针对有向无环图的概念,通常是用于将一些点进行拓扑排序之后形成一个序列能够形成先后的关系,所以拓扑排序可以用于解决点之间又先后关系的序列。

        POJ1094这道题是说给你一些大小关系,问你是否可以确定这n个字符确定的先后顺序,于是对每一次加入边后,进行拓扑排序,看是否形成了一个有向无环图,并且此时的序列是唯一的。因为题目要求中大小是一个确定序列,所以只有当拓扑排序之后的序列是确定的,那么就是确定了这个序列了的。

        题目中需要判断是否存在环,于是我们只需要在进行拓扑排序完成之后看看序列中的点的个数是否是n个,否则就是存在环。还有就是当我们是唯一确定一个序列的时候,那么这个时候 进行拓扑排序的过程中,队列中的点的个数必然是1,否则就是不确定的拓扑排序,这里需要小心判断,不然wa到死。

         注意好了这些就可以安安全全的ac了。下面贴上我的AC代码:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const int Max=26;
int indegree[Max];
vector<int> adj[Max];

int getVal(char ch)
{
    return ch-'A';
}

void init(int n)
{
    for(int i=0;i<n;i++)
    {
        adj[i].clear();
    }
    memset(indegree,0,sizeof(indegree));
}

int path[Max+2],plen;

int checkWrong(int n)
{
    int inde[Max];
    for(int i=0;i<n;i++)
        inde[i]=indegree[i];
    int flag=0;
    queue<int> q;
    for(int i=0;i<n;i++)
    {
        if(inde[i]==0)
        {
            q.push(i);
            flag++;
        }
    }
    plen=0;
    while(!q.empty())
    {
        int fr=q.front();
        if(q.size()>1)
            flag=2;
        q.pop();
        path[plen++]=fr;
        int len=adj[fr].size();
        for(int i=0;i<len;i++)
        {
            int next=adj[fr][i];
            inde[next]--;
            if(inde[next]==0)
            {
                q.push(next);
            }
        }
    }
    if(plen<n)
        return 1;
    if(plen==n&&flag==1)
        return 2;
    return 0;
}

int check(int st,int en)
{
    int len=adj[st].size();
    for(int i=0;i<len;i++)
    {
        if(adj[st][i]==en)
            return 1;//是重边
    }
    return 0;
}
int main()
{
    int n,m;
    int flag,ans,i;
    char s[20];
    while(scanf("%d %d",&n,&m))
    {

        if(n==0&&m==0)
            break;
        init(n);
        flag=0;
        for(i=1;i<=m;i++)
        {
            //cin>>s;
            scanf("%s",s);
           // cout<<s<<endl;
            int st=getVal(s[0]);
            int en=getVal(s[2]);
            if(check(st,en)==0)
            {
                adj[st].push_back(en);
                indegree[en]++;
            }
         //   printf("before check\n");
            int temp=checkWrong(n);
         //   printf("after checkWrong\n");
            if(temp==1)
            {
                flag=1;
                ans=i;
                break;
            }
            else if(temp==2)
            {
                flag=2;
                ans=i;
                break;
            }
        }
        for(i=i+1;i<=m;i++)
        {
            scanf("%s",s);
        }
        if(flag==0)
        {
            printf("Sorted sequence cannot be determined.\n");
        }
        else if(flag==1)
        {
            printf("Inconsistency found after %d relations.\n",ans);
        }
        else if(flag==2)
        {
            printf("Sorted sequence determined after %d relations: ",ans);
            for(i=0;i<plen;i++)
            {
                printf("%c",'A'+path[i]);
            }
            printf(".\n");
        }
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值