zoukankan      html  css  js  c++  java
  • poj1094Sorting It All Out 拓扑排序

      做拓扑排序的题目,首先要知道两条定理:

        1、最后得到的拓扑数组的元素个数如果小于n,则不存在拓扑序列。  (有圈)

        2、如果一次入队的入度为零的点数大于1,则拓扑序列不唯一。  (关系不确定)

      本题有一个默认的东西,如果到了第K(看K<m)步,能唯一确定一个序列,就不用管之后会不会产生矛盾。

      这题的思路还是比较清晰的。输入也只有X<Y(只有<符号,并且X,Y都只是大写字母),数据量比较小。不过边数没有限制,用链式前向星的话不太好,还是用邻接矩阵吧。每次用邻接矩阵要注意的是判断重边,做小生成树的时候是用初始化边为无穷大,然后每次取小的。但是这里没有边权,所以只要有边,赋值为1,就可以了。遇到重边的话,不能再加入度。

      只需要拓扑排序就可以解决这个问题了。我就犯了画蛇添足的错误,我居然用floyd去判圈。这主要是对拓扑排序理解不够的原因。当出现的字母的数字小于n时,没出现的字母的入度是零,所以不影响拓扑排序产生的数据元素的个数。只有有圈的情况才会使得数组元素个数小于n。

      还有,我犯了一个很二的错误。因为没输入一组数据就要做一次拓扑排序。我居然把统计入度的数组没有变化就用了。囧了。再声明一个数组,每次拓扑排序之前,把入度数组的数据复制过来就好了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 
     6 const int N = 30;
     7 int ind[N],que[N], g[N][N],id[N];
     8 int iq,flag, T;
     9 void topo(int n)
    10 {
    11     int i,k,j=0,x;
    12     T=0;
    13     for(i=1;i<=n;i++)
    14     {
    15         id[i]=ind[i];
    16         if(id[i]==0) que[j++]=i;
    17     }
    18     if(j>1) T=1;
    19     x=j;
    20     for(i=0;i<j;i++)
    21     {
    22         if(j-x>1) T=1;
    23         x=j;
    24         int u=que[i];
    25         for(k=1;k<=n;k++)
    26         {
    27             if(g[u][k]&&u!=k)
    28             {
    29                 id[k]--;
    30                 if(id[k]==0) que[j++]=k;
    31             }
    32         }
    33     }
    34     iq=j;
    35 }
    36 void init()
    37 {
    38     flag=0;
    39     memset(ind,0,sizeof(ind));
    40     memset(g,0,sizeof(g));
    41 }
    42 int main()
    43 {
    44     //freopen("test.txt","r",stdin);
    45     int n,m,i,j,k,t,a,b;
    46     char ch1,ch2,ch;
    47     while(scanf("%d%d",&n,&m)!=EOF)
    48     {
    49         if(!n) break;
    50         init();
    51         t=0;
    52         for(k=1;k<=m;k++)
    53         {
    54             do
    55                 scanf("%c",&ch1);
    56             while (!isalpha(ch1)) ;
    57             scanf("<%c",&ch2);
    58             if(flag) continue;
    59             a=ch1-64,b=ch2-64;
    60             if(a>n||b>n||a==b) flag=1;
    61             if(flag) {printf("Inconsistency found after %d relations.
    ",k);continue;}
    62             if(g[a][b]) continue;
    63             g[a][b]=1;
    64             ind[b]++;
    65             topo(n);
    66             if(iq<n){flag=1;printf("Inconsistency found after %d relations.
    ",k);continue;}
    67             if(iq==n&&!T){
    68                 flag=1;
    69                 printf("Sorted sequence determined after %d relations: ",k);
    70                 for(i=0;i<n;i++) printf("%c",que[i]+64);
    71                 printf(".
    ");
    72                 continue;
    73             }
    74             if(k==m&&!flag) printf("Sorted sequence cannot be determined.
    ");
    75         }
    76     }
    77     return 0;
    78 }
    View Code
  • 相关阅读:
    数组名与指向数组的指针
    如何实现带可变长参数的函数
    assert()的使用
    参数入栈的顺序以及栈/堆的生长顺序
    指向函数的指针
    各变量入栈顺序
    数组与指针
    C中空指针、NULL与0
    C中为什么不能用==比较字符串?
    在命令行窗口中输入EOF
  • 原文地址:https://www.cnblogs.com/Potato-lover/p/3947551.html
Copyright © 2011-2022 走看看