(第 k 小路径)给定一张 n 个点 m 条边的有向无环图,定点编号从 0 到 n−1,对于一条路径,我们定义“路径序列”为该路径从起点出发依次经过的顶点编号构成的序列。求所有至少包含一个点的简单路径中,“路径序列”字典序第 k 小的路径。保证存在至少 k 条路径。上述参数满足 1≤n,m≤105,1≤k≤1018。
在程序中,我们求出从每个点出发的路径数量。超过 1018 的数都用 1018 表示。然后我们根据 k 的值和每个顶点的路径数量,确定路径的起点,然后可以类似地依次求出路径中的每个点。
试补全程序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | #include <iostream> #include <algorithm> #include <vector> const int MAXN = 100000; const long long LIM = 100000000000000000011; int n, m, deg[MAXN]; std::vector<int> E[MAXN]; long long k, f[MAXN]; int next(std::vector<int> cand, long long &k) { std::sort(cand.begin(), cand.end()); for (int u : cand) { if (①) return u; k -= f[u]; } return -1; } int main() { std::cin >> n >> m >> k; for (int i = 0; i < m; ++i) { int u, v; std::cin >> u >> v; // 一条从u到v的边 E[u].push_back(v); ++deg[v]; } std::vector<int> Q; for (int i = 0; i < n; ++i) if (!deg[i]) Q.push_back(i); for (int i = 0; i < n; ++i) { int u = Q[i]; for (int v : E[u]) { if (②) Q.push_back(v); --deg[v]; } } std::reverse(Q.begin(), Q.end()); for (int u : Q) { f[u] = 1; for (int v : E[u]) f[u] = ③; } int u = next(Q, k); std::cout << u << std::endl; while (④) { ⑤; u = next(E[u], k); std::cout << u << std::endl; } return 0; } |
0 of 5 Questions completed
Questions:
You have already completed the quiz before. Hence you can not start it again.
Quiz is loading…
You must sign in or sign up to start the quiz.
You must first complete the following:
0 of 5 Questions answered correctly
Your time:
Time has elapsed
You have reached 0 of 0 point(s), (0)
Earned Point(s): 0 of 0, (0)
0 Essay(s) Pending (Possible Point(s): 0)
①处应填()
2. ②处应填()
3. ③处应填()
4. ④处应填()
5. ⑤处应填()