• POJ1094(Topological Sort)


    1094:Sorting It All Out

    时间限制:     

    1000ms  

    内存限制:     

    65536kB 

    描述

    An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from smallest to largest. For example, the sorted sequence A, B, C, D implies that A < B, B < C and C < D. in this problem, we will give you a set of relations of the form A < B and ask you to determine whether a sorted order has been specified or not.

    输入 

    Input consists of multiple problem instances. Each instance starts with a line containing two positive integers n and m. the first value indicated the number of objects to sort, where 2 <= n <= 26. The objects to be sorted will be the first n characters of the uppercase alphabet. The second value m indicates the number of relations of the form A < B which will be given in this problem instance. Next will be m lines, each containing one such relation consisting of three characters: an uppercase letter, the character "<" and a second uppercase letter. No letter will be outside the range of the first n letters of the alphabet. Values of n = m = 0 indicate end of input.

    输出

    For each problem instance, output consists of one line. This line should be one of the following three:

    Sorted sequence determined after xxx relations: yyy...y.
    Sorted sequence cannot be determined.
    Inconsistency found after xxx relations.

    where xxx is the number of relations processed at the time either a sorted sequence is determined or an inconsistency is found, whichever comes first, and yyy...y is the sorted, ascending sequence.

    样例输入

    4 6

    A<B

    A<C

    B<C

    C<D

    B<D

    A<B

    3 2

    A<B

    B<A

    26 1

    A<Z

    0 0

    样例输出

    Sorted sequence determined after 4 relations: ABCD.

    Inconsistency found after 2 relations.

    Sorted sequence cannot be determined.

    Help1:拓扑排序:先判断是否有环,再判断是否有序,最后才能判断是否能得出结果。必须遍历完整个图才能知道是否有环。

    Help2:在网上看到这样的提示 
    “对于前i-1条边已确立完整的拓扑关系但是在第i条边后又出现环的输入,算作无环图,也就是说,对于输入2 2 A<B B<A,应输出Sorted sequence determined after 1 relations: AB,而且题目和范例都没有提到这一点,吐血” 

    Help3第一次很快用拓扑排序把代码敲出来,提交,wa,仔细分析后,发现忽略了重复边的情况,插入边(u, v),如果图g已经存在了边(u,v),就不能再增加v的入度。
    很快改过来,提交,还是wa,很无奈,上网看看大牛评论,原来是只要当前输入数据能确定唯一,及时后面输入数据有环,也是判定为确定唯一。也就是说,每输入一条边,如果判定有结果,忽略后面输入数据,即使后面输入数据能改变结果。
    再改,再提交,还是wa,几度欲放弃之,还是坚持下来了,上google找别人代码来分析,结果发选只要当前输入数据有环,及时当前输入数据不能确定唯一,也是判定为有环

    Help4题意就不说了,很明显的拓扑排序。借这道题总结一下拓扑排序吧。拓扑排序的思路很明确但我总觉得有很多的细节值得注意,写的时候总是缺点这少点那的,不断的调试总是浪费很多的时间,以下是我总结的几点:

    (1)拓扑排序的结果一般分为三种情况:1、可以判断 2、有环出现了矛盾 3、条件不足,不能判断,思路上一定要分清楚三种情况的条件判断。

    (2)初始化栈的时候,将入度为零的顶点入栈,然后弹出栈顶元素e,将e的邻接点的入度减一,若邻接点的入度也为零了,将该邻接点也入栈,如此循环,直到栈空。在这个过程中,栈中元素个数始终为一。若大于一则出现了多个顶点入度为零的情况,这时就无法辨别这几个顶点的先后顺序,这也就是条件不足的情况。若入度为零的顶点的个数为零,也就出现了环的情况,但这一情况必须是在弹出的元素的个数小于顶点总个数,所以在结束的时候需要将计数器与总个数相比较,因为会出现这样的情况:A<B,B<C,C<A,D<E,一开始时将D进栈,然后D出E进,E出时没有元素可进了,若不在最后再进行一次比较的话,那么就认为可以判断了,然而其实是有环的。

    再说说这道题吧,这道题不仅需要判断这三种情况,而且还要判断在处理第几个关系时出现前两种情况,对于本道题来说三种情况是有优先级的。前两种情况是平等的谁先出现先输出谁的相应结果,对于第三种情况是在前两种情况下都没有的前提下输出相应结果的。

    附带几组测试数据:

    6 5
    A<D
    B<C
    A<B
    D<E
    C<D
    Sorted sequence cannot be determined.

    6 6
    A<D
    B<C
    E<F
    B<A
    D<E
    A<B
    Inconsistency found after 6 relations.

    6 6
    D<E
    B<F
    A<D
    F<C
    A<F
    E<B
    Sorted sequence determined after 6 relations: ADEBFC.

    3 3
    A<B
    B<C
    C<A
    Sorted sequence determined after 2 relations: ABC.

    4 6
    A<B
    A<C
    B<C
    C<D
    B<D
    A<B
    Sorted sequence determined after 4 relations: ABCD.

    3 2
    A<B
    B<A
    Inconsistency found after 2 relations.

    2 2
    A<B
    B<A
    Sorted sequence determined after 1 relations: AB.

    2 0

    Sorted sequence cannot be determined.

     

    #include"iostream"
    #include"queue"
    #include"vector"
    #include"cstring"//for memset
    using namespace std;
    int mat[26][26];
    int updating[26][26];
    //以下两个全局用于topo函数,注意要实时更新
    vector<int> sorted(26);
    bool has_add[26];
    bool topo(int pass[26][26],int num,int times);
    int main()
    {
     int n,x;
     char temp[4];
     while(cin>>n>>x&&!(n==0&&x==0))
     {
      memset(mat,0,sizeof(mat));//初始状态没有弧和路径
      bool done=false;//初始done值为false
      for(int i=0;i<x;i++)//for循环逐步构造弧并寻找路径
      {
       cin>>temp;
                mat[temp[0]-'A'][temp[2]-'A']=1;
       if(!done)//当已经确定顺序后,后面输入的规则就没有用了
       {
        done=topo(mat,n,i+1);//i+1是判定条件的数目,最后一次是先输出结果再返回true
       }
      }
      if(!done)       
       cout<<"Sorted sequence cannot be determined.\n";        
     }      
    }        
    bool topo(int pass[26][26],int num,int times)
    {
     for(int i=0;i<num;i++)//复制pass给updating
      for(int j=0;j<num;j++)
       updating[i][j]=pass[i][j];  
     //刷新sorted和has_add             
     sorted.clear();         
     memset(has_add,false,sizeof(has_add));       
     int will_add;//用于存储将要入队的节点并作为监视哨
     while(1)
     {
        //以下利用for循环查找入度为0的节点,逐步增长路径长度
     //注意了,for循环外面要用while(1),再利用has_add[i]来控制是否跳出while循环,
        //因为入度为0的节点不一定是总是循环开头的0,而有可能是i++后的其他数
     will_add=-1;//监视哨,当n个节点除了已经入队于sorted_res中的节点后没有一个是入度为0的时候
     for(int i=0;i<num;i++)   
     {   
      if(has_add[i]==true)    
       continue;  
           bool can_add=true;
        for(int j=0;j<num;j++)//寻找入度为0的节点以入队
        {
              can_add=can_add&&(updating[j][i]==0);        
        }                                                                              
        if(can_add)             
        {              
        will_add=i;                 
        break;                        
        }                                                
     }//end outer for     
     if(will_add==-1)//处理监视哨,跳出while(1)循环,当n个节点除了已经入队于sorted_res中的节点后没有一个是入度为0的时候
      break;
      has_add[will_add]=true;       
      sorted.push_back(will_add);           
          //后期处理,删除所有以当前节点为弧头的弧        
          for(int j=0;j<num;j++)                         
        updating[will_add][j]=0;         
     }//end while(1)
     if(sorted.size()<num)
     {
      cout<<"Inconsistency found after "<<times<<" relations.\n";
       return true;                            
     }     
     bool strict=true;
     if(sorted.size()==num)
     {
       for(int i=0;i<sorted.size()-1;i++)
       {
        strict=strict&&(pass[sorted[i]][sorted[i+1]]==1);//此处必须用pass来判定序列是否完全确定为有序
       }
     }
     if(strict==true)           
     {
       cout<<"Sorted sequence determined after "<<times<<" relations: ";
       for(int i=0;i<sorted.size();i++)
        cout<<(char)(sorted[i]+'A');
       cout<<"."<<endl;
       return true;
     }
     else
          return false;
    }

  • 相关阅读:
    AM8 自定义表情包的实现方法
    Create STKNetDiskC Instance Error
    怎样实现文件发文功能
    企业云盘的数据备份
    一种可行的文档协同编辑方法实现
    【OI】二分图最大匹配
    【OI】位运算操作
    【OI】关于快速幂的简单理解
    【OI】线性筛
    【OI】指针线段树&指针
  • 原文地址:https://www.cnblogs.com/lzhitian/p/2140069.html
Copyright © 2020-2023  润新知