POJ 1094 Sortint it all out

<span style="font-family:SimHei;font-size:14px;">这道题花了我好长时间,主要思路就是是拓扑排序,但是许多细节问题要注意。首先就是优先输出环路,即存在矛盾,无法比较大小;然后是能够比较大小;最后才是条件不足,无法比较。一开始我三种情况都考虑了,结果在编程的时候就会存在环路和条件不足先后的矛盾,其实只要前两种情况不满足,肯定就是第三种情况,所以所写程序只要能判定前两种情况即可。所以我再次修改程序,然后注意一些细节,终于成功AC了。</span>
<span style="font-family:SimHei;font-size:14px;"></span><pre name="code" class="cpp">#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<vector>
using namespace std;
const int N=27;
bool graph[N][N],outdegree[N];//outdegree用来记录第i次输入时一共有多少个字母已经存在。
int indegree[N],n,m;
char s[N];
int topol_sort()
{
    int index=0,count_exist=0;//index用来计数,也就是这次比较一共产生了多少个入读为零的点;count_exist用来存储该次一共要比较多少个数。
    char s_temp[N];//临时数组用来存储字符串
    bool ismultiple=false;//用来判断是否有入度大于等于2的点
    for(int i=0;i<n;i++)
        if(outdegree[i])
        count_exist++;
    //printf("count_exist:%d\n",count_exist);
    int t[N];//临时存储indegree数组,因为要多次比较,所以如果不用这个,indegree数组就会改变。
    for(int i=0;i<n;i++)
    {
        t[i]=indegree[i];
        //printf("t[%d]:%d\n",i,t[i]);
    }
    stack<int> s_alpha;
    while(true)
    {
        int count=0,temp;
        for(int i=0;i<n;i++)
        {
            if(t[i]==0&&outdegree[i])
            {
                count++;
                s_alpha.push(i);
                t[i]=-1;
                s_temp[index++]=(char)(i+'A');
            }
        }
        //printf("count:%d index:%d\n",count,index);
        if(count==0&&index==count_exist&&count_exist<n)
            return 0;
        else if(count==0&&index==count_exist&&ismultiple)//注意着两种情况,一开始自己没有想到,结果不对。细节还是很重要的。
            return 0;
        if(count>=2)
            ismultiple=true;
        if(count==0&&index<count_exist)//当没有入度为0的点,并且此时index<count_exist说明存在环
            return 1;
        if(index==count_exist&&index==n&&count==0&&ismultiple==false)//满足此条件说明成功排序了。
        {
            for(int i=0;i<n;i++)
                s[i]=s_temp[i];
            return 2;
        }
        while(!s_alpha.empty())
        {
            temp=s_alpha.top();
            s_alpha.pop();
            for(int i=0;i<n;i++)
                if(graph[temp][i])
                    t[i]--;
        }
    }
    return 0;
}
int main()
{
    char s1[5];
    int result,loop,ok;
    bool is_ok,is_loop;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)
            break;
        is_ok=false,is_loop=false;
        memset(graph,false,sizeof(graph));
        memset(indegree,0,sizeof(indegree));
        memset(outdegree,false,sizeof(outdegree));
        for(int i=1;i<=m;i++)
        {
            scanf("%s",s1);
            if(is_ok||is_loop)
                continue;
            int a=s1[0]-'A';
            int b=s1[2]-'A';
            if(graph[a][b]==false)
            {
                graph[a][b]=true;
                indegree[b]++;
                outdegree[a]=outdegree[b]=true;
            }
            result=topol_sort();
            if(result==1)
            {
                is_loop=true;
                loop=i;
            }
            else if(result==2)
            {
                is_ok=true;
                ok=i;
            }
        }
        if(is_loop)
            printf("Inconsistency found after %d relations.\n",loop);
        else if(is_ok)
        {
            printf("Sorted sequence determined after %d relations: ",ok);
            for(int i=0;i<n;i++)
                printf("%c",s[i]);
            printf(".\n");
        }
        else
            printf("Sorted sequence cannot be determined.\n");
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值