题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=60
很明显是拓扑排序,但是以前学的拓扑排序有漏洞,不能做这道题,所以看了解析,提供了另一种拓扑排序的方法,可以返回三种信息:排序成功、关系矛盾、关系不确定。
这个方法,强化记忆吧。
#include<cstdio> const int MAXN = 30; int data[MAXN][MAXN]; int sorted[MAXN]; int n, m; int topologic(int left[], int right[], int used[]) { int judge[MAXN]; int sameLayer[MAXN]; int count = 0; int order = 1; int i, j; for (i=1; i<MAXN; i++) { judge[i] = right[i]; if (!used[i]) judge[i] = -1; } while (true) { int total = 0; i = 1; while (i <= n) { while ((i <= n) && (judge[i] != 0)) i++; if (i > n) break; sameLayer[++total] = i; judge[i] = -1; sorted[++count] = i; } if (total == 0) break; if (total > 1) order = 0; for (j=1; j<=total; j++) { i = sameLayer[j]; for (int k=1; k<=left[i]; k++) judge[data[i][k]]--; } } if (count == n) { if (!order) return -1; return 0; } if (count < n) { for (i=1; i<=n; i++) if (judge[i] > 0) return 1; return -1; } } int main() { int relation[MAXN * MAXN][2]; int right[MAXN], left[MAXN]; int used[MAXN]; while (scanf("%d%d\n",&n,&m) && n) { for (int i=0; i<MAXN; i++) left[i] = right[i] = used[i] = sorted[i] = 0; char three[10]; for (int i=0; i<m; i++) { scanf("%s",three); relation[i][0] = three[0] - 'A' + 1; relation[i][1] = three[2] - 'A' + 1; } int result = 0; for (int i=0; i<m; i++) { int x = relation[i][0]; int y = relation[i][1]; data[x][++left[x]] = y; ++right[y]; used[x] = 1; used[y] = 1; int flag = topologic(left, right, used); if (flag == 0) { printf("Sorted sequence determined after %d relations: ",i+1); for (int j=1; j<=n; j++) printf("%c",(char)(sorted[j]+64)); printf(".\n"); result = 1; break; } if (flag == 1) { printf("Inconsistency found after %d relations.\n",i+1); result = 1; break; } } if (!result) printf("Sorted sequence cannot be determined.\n"); } return 0; }拓扑排序模板:
#include<iostream> #include<memory.h> #define MAXN 500 using namespace std; int data[MAXN][MAXN]; int sorted[MAXN]; int n, m; int topologic(int left[], int right[], bool used[]) { int judge[MAXN]; int sameLayer[MAXN]; int count = 0; bool order = true; int i, j; for (i=1; i<MAXN; i++) { judge[i] = right[i]; if (!used[i]) judge[i] = -1; } while (true) { int total = 0; i = 1; while (i <= n) { while (i <=n && judge[i] != 0) i++; if (i > n) break; sameLayer[++total] = i; judge[i] = -1; sorted[++count] = i; } if (total == 0) break; if (total > 1) order = false; for (j=1; j<=total; j++) { i = sameLayer[j]; for (int k=1; k<=left[i]; k++) judge[data[i][k]]--; } } if (count == n) { if (!order) return -1; return 0; } if (count < n) { for (i=1; i<=n; i++) if (judge[i] > 0) return 1; return -1; } } int main() { int right[MAXN], left[MAXN]; //入度和出度 bool used[MAXN]; memset(right,0,sizeof(right)); memset(left,0,sizeof(left)); memset(used,false,sizeof(used)); cin>>n>>m; for (int i=0; i<m; i++) { int x, y; cin>>x>>y; data[x][++left[x]] = y; ++right[y]; used[x] = true; used[y] = true; } int flag = topologic(left, right, used); switch (flag) { case -1:cout<<"无法判断关系!"<<endl; break; case 1:cout<<"关系矛盾!"<<endl; break; default: { cout<<"拓扑排序的结果如下:"<<endl; for (int i=1; i<=n; i++) cout<<sorted[i]<<' '; cout<<endl; } } return 0; }