本题要求输出所有拓扑排序的序列。
还好本题的数据量不是非常大。限制在26个大写英文字母,故此能够使用递归法输出。
这个递归输出所有解在Leetcode非常多这种题目的,不小心的话,还是非常难调试的。
整体考了递归和拓扑排序,还有推断能否够拓扑排序-就是是否图有环。
考了三大知识点。难度还是有的。由于数据量不大,故此推断环能够使用一般递归方法。递归仅仅须要注意细节就好了。
#include <stdio.h> #include <vector> #include <string.h> using namespace std; const int ALPHA = 26; bool gra[ALPHA][ALPHA]; int id = 0, len = 0; const int MAX_B = 512; char buf[MAX_B]; char getFromBuf() { if (id >= len) { len = fread(buf, 1, MAX_B, stdin); id = 0; } return buf[id++]; } struct Subset { int p, r; }; Subset subs[ALPHA]; int findParent(int u) { if (u != subs[u].p) subs[u].p = findParent(subs[u].p); return subs[u].p; } void unionTwo(int x, int y) { int xroot = findParent(x); int yroot = findParent(y); if (subs[xroot].r < subs[yroot].r) subs[xroot].p = yroot; else { subs[yroot].p = xroot; if (subs[yroot].r == subs[xroot].r) subs[xroot].r++; } } void initSubs() { for (int i = 0; i < ALPHA; i++) { subs[i].p = i; subs[i].r = 0; } } bool isCycle() { initSubs(); for (int i = 0; i < ALPHA; i++) { for (int j = 0; j < ALPHA; j++) { if (i == j || !gra[i][j]) continue; int ip = findParent(i); int jp = findParent(j); if (ip == jp) return true; unionTwo(i, j); } } return false; } int rs[ALPHA]; bool vis[ALPHA]; void printAllTopologicalOrders(int N, int rsid = 0) { if (rsid == N) //递归究竟了,打印结果 { if (rsid > 0) putchar(rs[0]+'A'); for (int i = 1; i < rsid; i++) { putchar(' '); putchar(rs[i]+'A'); } putchar(' '); return ; } for (int i = 0; i < ALPHA; i++) { if (vis[i]) continue;//这里要推断,漏了这句。好难dubg啊。要细致用脑去模拟过程才干发现!!
!
if (!gra[i][i]) continue; //没有这个点,跳过 int j = 0; for ( ; j < ALPHA; j++)//检查i是否有入度 { if (i != j && !vis[j] && gra[j][i]) break; } if (j == ALPHA) //找到入度为零的点i了 { vis[i] = true; rs[rsid] = i; printAllTopologicalOrders(N, rsid+1); vis[i] = false; } } } int main() { int T; scanf("%d", &T); while (T--) { int N = 0; memset(gra, 0, sizeof(gra)); char a = getFromBuf(); while ((a == ' ' || a == ' ') && len) a = getFromBuf(); while (a != ' ' && len) { if ('A' <= a && a <= 'Z') { gra[a-'A'][a-'A'] = 1;//代表有点 N++; } a = getFromBuf(); } while ((a == ' ' || a == ' ') && len) a = getFromBuf(); while (a != ' ' && len) { int u = a - 'A'; a = getFromBuf(); a = getFromBuf(); int v = a - 'A'; gra[u][v] = 1; a = getFromBuf(); if (a == ' ') break; a = getFromBuf(); } fill(vis, vis+ALPHA, false); if (isCycle()) puts("NO"); else { printAllTopologicalOrders(N); } if (T) putchar(' '); } return 0; }