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