zoukankan      html  css  js  c++  java
  • POJ1094Sorting It All Out

    转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1299234850

    提示:拓扑排序
    这道题有隐含这一信息,每输入一对关系,如果判定有结果,则可以忽略后面输入数据,即使后面输入数据能改变结果,也不用管。所以应该每输入一个关系就去更新当前的图,然后进行一趟拓扑排序。一旦产生结果,再对后面的数据处理下,就可以输出结果。

     

    所有可能的情况罗列:

     

    (独家经验原创,重中之重!可以说没有这些,这题就无法AC!)

    一、当输入的字母全部都在前n个大写字母范围内时:

    (1)       最终的图 可以排序:

             在输入结束前如果能得到最终的图(就是用这n个字母作为顶点,一个都不能少);

    而且最终得到的图  无环;

                      只有唯一一个 无前驱(即入度为0)的结点,但允许其子图有多个无前驱的结点。

    在这步输出排序后,不再对后续输入进行操作

    2)输出矛盾

          在输入结束前如果最终图的子图有环

        在这步输出矛盾后,不再对后续输入进行操作

    3)输出无法确认排序

         这种情况必须全部关系输入后才能确定,其中又有2种可能

    ①最终图的字母一个不缺,但是有多个  无前驱结点

    ②输入结束了,但最终的图仍然字母不全,与 无前驱结点 的多少无关

    二、当输入的字母含有 非前n个大写字母 的字母时(超出界限):

    (1)       输出矛盾

    输入过程中检查输入的字母(结点),若 n个大写字母 全部出现,则在最后一个大写字母出现的那一步 输出矛盾

    (2)       输出无法确认排序

    最后一步输入后,前n个大写字母 仍然未全部出现,则输出 无法确认排序

     

    PS:在使用“无前驱结点”算法时必须要注意,在“矛盾优先”的规律下,必须考虑一种特殊情况,就是多个无前驱结点与环共存时的情况,即输入过程中子图都是有 多个无前驱结点,最后一步输入后出现了环,根据算法的特征,很容易输出“不能确认排序”,这是错的,必须适当修改算法,输出“矛盾”。

    例如:

    6 6

    A<F

    B<D

    C<E

    F<D

    D<E

    E<F

    输出矛盾

      1 //Memory Time 
    2 //276K 0MS
    3
    4 #include<iostream>
    5 using namespace std;
    6
    7 int n,m; //n结点下限,m关系对
    8 char top_out[26]; //排序输出列表
    9 int po=0; //输出列表的指针
    10
    11 typedef class degree
    12 {
    13 public:
    14 int in; //入度
    15 char to[26]; //记录指向的所有顶点,以便删除出度的操作
    16 int pt; //数组to的指针
    17 };
    18
    19 int top_sort(degree alph[],bool mark[],int num)
    20 {
    21 /*假设图G的当前子图为F*/
    22
    23 memset(top_out,'\0',sizeof(top_out));
    24 po=0;
    25
    26 int del_n=0;
    27 int zero=0; //记录图F中入度为0的结点个数
    28 for(int i='A';i<'A'+n;i++)
    29 if(mark[i] && !alph[i].in)
    30 zero++;
    31
    32 bool flag=false;
    33 while(zero>0)
    34 {
    35 if(zero>1) //图F的无前驱结点的个数不唯一,排序无法确定
    36 flag=true; //考虑到"矛盾"的优先性,避免在多个0入度结点情况下,最后一步输入刚好出现环(此时为矛盾)
    37 //所以这里先不返回值,而是先标记,执行拓扑,根据情况决定返回值
    38
    39 for(int k='A';k<='A'+n;k++) //寻找图F的唯一的前驱结点
    40 if(mark[k] && !alph[k].in)
    41 {
    42 mark[k]=false; //删除图F的唯一无前驱结点k
    43 del_n++; //记录删除的结点数
    44 top_out[po++]=k; //k记录到排序输出列表
    45 for(int i=0;i<alph[k].pt;i++) //删除结点k的所有出度边
    46 alph[ alph[k].to[i] ].in--;
    47 break;
    48 }
    49
    50 zero=0;
    51 for(int j='A';j<='A'+n;j++)
    52 if(mark[j] && !alph[j].in)
    53 zero++;
    54 }
    55
    56 if(flag && del_n==num)
    57 return 3;
    58 if(del_n<num) //说明图F存在有向环,矛盾,与0入度结点的多少无关。因为矛盾优先
    59 return 2;
    60 if(!flag && del_n==num && del_n<n) //图F能排序,但不能确定图G是否能排序,还需继续输入观察
    61 return 3;
    62 if(!flag && del_n==n) //图G能排序
    63 return 1;
    64 }
    65
    66 int main(void)
    67 {
    68 int num; //标记前n个字母出现个数,用于最终检查是否前n个字母均已被读入
    69 //*_t[]是用于备份的额外数组
    70 bool mark['Z'+1],mark_t['Z'+1]; //标记当前图G所使用的字母(结点)
    71 degree alph['Z'+1],alph_t['Z'+1];
    72
    73 while(true)
    74 {
    75 /*Input*/
    76
    77 cin>>n>>m;
    78
    79 if(!n||!m)
    80 break;
    81
    82 /*Initial*/
    83
    84 memset(mark,false,sizeof(mark));
    85 memset(mark_t,false,sizeof(mark_t));
    86 num=0;
    87
    88 for(int k='A';k<'A'+n;k++)
    89 {
    90 alph[k].in=alph_t[k].in=0;
    91 alph[k].pt=alph_t[k].pt=0;
    92 memset(alph[k].to,'\0',sizeof(alph[k].to));
    93 memset(alph_t[k].to,'\0',sizeof(alph_t[k].to));
    94 }
    95
    96 /*Structure Maps*/
    97
    98 char x,symbol,y; //临时变量
    99 bool flag=false;
    100 bool sign=false;
    101 int value; //记录拓扑返回的值
    102 int step; //记录当前情况发生的步骤
    103 for(int pair=1;pair<=m;pair++)
    104 {
    105 cin>>x>>symbol>>y;
    106
    107 if(x>='A'+n || y>='A'+n) //当输入的结点不在前n个字母范围内时
    108 sign=true; //不再进行拓扑,单纯检查后续输入是否把前n个字母都输入了
    109 //为了区分非前n个字母的字母的输入时间,是在确认了排序或矛盾之前还是之后
    110 //在确认 排序或矛盾之前:flag=false,sign=true
    111 //在确认 排序或矛盾之后:flag=true,sign=true
    112
    113 if(!mark[x] && x<'A'+n)
    114 num++;
    115 if(!mark[y] && y<'A'+n)
    116 num++;
    117
    118 if(!flag && !sign)
    119 {
    120 value=0;
    121
    122 mark[x]=mark[y]=true; //顶点标记
    123 mark_t[x]=mark_t[y]=true;
    124
    125 alph[y].in++; //入度标记
    126 alph_t[y].in++;
    127
    128 alph[x].to[ alph[x].pt++ ]=y; //指向标记 & 指针移动
    129 alph_t[x].to[ alph_t[x].pt++ ]=y;
    130
    131 /*Top-Sort & Sign*/
    132
    133 value=top_sort(alph_t,mark_t,num); //每次输入后图都被更新,要重新拓扑
    134 if(value==1) //排序确认
    135 {
    136 step=pair; //记录确认排序的位置
    137 flag=true; //不再对后续输入处理
    138 }
    139 else if(value==2) //矛盾
    140 {
    141 step=pair; //记录矛盾发生的位置
    142 flag=true; //不再对后续输入处理
    143 }
    144 else if(value==3 && pair<m) //排序(暂时)无法确认,需继续处理后续输入
    145 for(int k='A';k<'A'+n;k++) //数据还原
    146 {
    147 mark_t[k]=mark[k];
    148 alph_t[k].in=alph[k].in;
    149 }
    150
    151 if(pair==m && value==0)
    152 value=3;
    153 }
    154
    155 if(sign && !flag && num==n) //在确认 排序或矛盾之前,当存在有非前n个字母的结点时的"矛盾"
    156 {
    157 step=pair;
    158 value=2;
    159 }
    160 else if(sign && !flag && pair==m && num<n) //在确认 排序或矛盾之前,当存在有非前n个字母的结点时的"无法确认排序"
    161 value=3;
    162 }
    163
    164 if(value==1)
    165 {
    166 cout<<"Sorted sequence determined after "<<step<<" relations: ";
    167 for(int i=0;i<po;i++)
    168 cout<<top_out[i];
    169 cout<<'.'<<endl;
    170 }
    171 else if(value==2)
    172 cout<<"Inconsistency found after "<<step<<" relations."<<endl;
    173 else if(value==3)
    174 cout<<"Sorted sequence cannot be determined."<<endl;
    175 }
    176 return 0;
    177 }

  • 相关阅读:
    stl 之 next_permutation 求出一个排序的下一个排列的函数 转载
    算法学习一~分治法~二分查找,快速的找~
    Cocos2d开发系列(九)
    每个好架构师都是一位出色的程序员
    本地通知和推送通知编程指南(2)
    【Cocos2d游戏开发之十二】浅析使用C++/C/OC进行iOS游戏混编出现“failed with exit”问题与小结;
    【Cocos2d游戏开发之十三】CCSprite利用Bezier(贝塞尔)做抛物线动作并让CCSprite同时播放两个Action动作!
    【Cocos2d游戏开发之八】开启高清(960*640)模式问题与解答、图片适配以及设置iphone横竖屏
    使用SQL 2008进行INSERT操作
    【Cocos2d游戏开发之十一】使用Box2d物理系统以及在cocos2d框架添加Box2d物理系统lib包的方法
  • 原文地址:https://www.cnblogs.com/lyy289065406/p/2121720.html
Copyright © 2011-2022 走看看