poj1094&&zoj1060 Sorting It All Out ——拓扑排序入门题

题目链接:http://poj.org/problem?id=1094 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=60

题目大意:

  输入两个整数,n, m 分别表示以下的字母在字母表前 n 个字母范围内,有 m 行,每行描述一个大小关系,只有小于号。如果从开始到某一个关系式可以确定最终的序列,就输出确定的序列。如果得到矛盾,就输出到此经历的几个关系式。如果最终都没有确定,就输出序列不能确定的信息。

题目思路:

  边读入,边建图,每读入一条表达式,就拓扑排序判断是不是可以确定最后的序列了。如果可以得到最后包含全部n个字母的序列,后面的表达式只需要输入,但是不需要处理了。如果过程中到达一个表达式的时候,找到了一个环,就说明肯定不能确定最后的序列了。也不需要处理后面的表达式了。如果一直都没有确定,就一直处理。

  这题大体上的思路是这样,但是还是有一些细节没有处理好。最严重的就是:如何在中间的过程中去判断环。不能单纯地比较弹栈的顶点个数和 n 的大小,因为可能读入的顶点个数还没有到达 n的时候,就已经出现环了,这样,以后的输入就不用处理了。如何处理呢?我的方法就是,当前剩下的点当中,是不是还存在度数大于0的点,用bug标记,因为这个bug调试了好久。。如果存在的话,就说明返回-1,表示存在环。为什么会出现这个bug呢?因为这个涉及到到第几条表达式出现矛盾的问题。

  主要还是思维不严谨,虽然后来测试数据过了,但还是不知道哪里错了,后来自己出了几组数据才发现那个bug。这题做了好久,有的人一下就过了,可是我却卡了两天……教训就是:遇到bug了不能慌,分析一下是不是自己当初的想法错了,还是哪个细节没有处理好。即使有一个细节处理不好,程序最后都会崩溃。还有就是,可能自己的处理方法不好,导致最后的bug超多,代码也超级繁琐……一开始就应该想清楚,有没有更好的处理办法,尤其是一些细节问题。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <cctype>
  6 #include <stack>
  7 #include <queue>
  8 #include <map>
  9 #include <set>
 10 #include <vector>
 11 #include <cmath>
 12 #include <algorithm>
 13 #define lson l, m, rt<<1
 14 #define rson m+1, r, rt<<1|1
 15 using namespace std;
 16 typedef long long int LL;
 17 const int MAXN =  0x3f3f3f3f;
 18 const int  MIN =  -0x3f3f3f3f;
 19 const double eps = 1e-9;
 20 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1},
 21   {1,1},{1,-1},{-1,-1}};
 22 bool edge[27][27];
 23 int n, m, rela;
 24 string s, out;
 25 map<int,bool> mymap;
 26 int Count[27], mystack[27], Count1[27];
 27 int topsort(int ki)
 28 {
 29   out.clear();
 30   int i, j, k, top = 0, cnt = 0; int bug = 0;
 31   bool flag = true;
 32   for (i = 0; i < 27; ++i) {
 33     mystack[i] = 0;
 34     Count1[i] = Count[i];
 35   }
 36   for (i = 0; i < n; ++i) {
 37     if (mymap[i] && Count1[i]==0) {
 38       Count1[i]--; mystack[++top] = i; cnt++;
 39       out += (i+'A');
 40     }
 41   }
 42   if (top > 1) flag = false;
 43   while (top>0) {
 44     j = mystack[top];
 45     top--;
 46     for (i = 0; i < n; ++i) {
 47       if (mymap[i] && edge[j][i]==true) {
 48         Count1[i]--;
 49       }
 50     }
 51     for (i = 0; i < n; ++i) {
 52       if (mymap[i] && Count1[i]==0) {
 53         Count1[i]--; mystack[++top] = i; cnt++;
 54         out += (i+'A');
 55       }
 56     }
 57     if (top > 1) flag = false;
 58   }
 59   for (i = 0; i < n; ++i) {
 60     if (Count1[i] > 0) {
 61       bug++; break;
 62     }
 63   }
 64   if (top == 0 && bug > 0) return -1;
 65   if (flag == false) return 0;
 66   return cnt;
 67 }
 68 int main(void){
 69 #ifndef ONLINE_JUDGE
 70   freopen("poj1094.in", "r", stdin);
 71   freopen("out", "w", stdout);
 72 #endif
 73   int i, j, k;
 74   while (~scanf("%d%d", &n, &m) && (m||n)) {
 75     out.clear();
 76     mymap.clear(); memset(edge, false, sizeof(edge));
 77     int mrk = 0, kind = 0, pai = 0, cnt = 0; rela = 0;
 78     for (i = 0; i < 27; ++i) Count[i] = 0;
 79     for (i = 0; i < m; ++i) {
 80       cin >> s;
 81       if (mrk == 1 || mrk == -1) continue;
 82       int u, v;
 83       rela++;
 84       u = s[0] - 'A'; v = s[2] - 'A';
 85       if (!mymap[u]) mymap[u]=true, kind++;
 86       if (!mymap[v]) mymap[v]=true, kind++;
 87       if (edge[u][v]==false) {
 88         edge[u][v] = true;
 89         Count[v]++;
 90       }
 91       pai = topsort(kind);
 92       if (pai == n ) mrk = 1;
 93       if (pai == -1) mrk = -1;
 94     }
 95     if (pai != 0 && pai < kind) mrk = -1;
 96     if (mrk == 1)
 97       printf("Sorted sequence determined after %d relations: ", rela), cout << out <<'.'<<endl;
 98     else if (mrk == -1)
 99       printf("Inconsistency found after %d relations.\n", rela);
100     else if (mrk == 0)
101       printf("Sorted sequence cannot be determined.\n");
102   }
103 
104   return 0;
105 }

  这题过的好辛苦。但是过了之后,才发现,自己原来陷入了思维的误区,一些细节自己根本没有考虑到。思维定式,总是想着自己的处理方法是对的。然后就花很长时间也找不出来错……

posted on 2013-05-01 01:23  aries__liu  阅读(147)  评论(0编辑  收藏  举报