五月集训(第30天)—拓扑排序
拓扑排序
1. 207. 课程表
思路:
拓扑排序模板题,思路在代码注释中。
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
int prerequisites_size = prerequisites.size(), i;
vector<vector<int>> edge(numCourses);
queue<int> q;
int _in[numCourses];
memset(_in, 0, sizeof(_in));
for (i = 0; i < prerequisites_size; ++i) {
int u = prerequisites[i][1];
int v = prerequisites[i][0];
edge[u].push_back(v); /* u->v 学完u可以学v */
++_in[v]; /* 多一门先修课,入度+1 */
}
for (i = 0; i < numCourses; ++i) { /* 将入度为0的课加入队列,先学没有先修课(或先修课已经上过了)的课 */
if (_in[i] == 0) q.push(i);
}
while (!q.empty()) { /* 一直上当前可以上的课,直到无课可上 */
int u = q.front();
q.pop();
int n = edge[u].size();
for (i = 0; i < n; ++i) { /* 当前学完的课是哪门课的先修课,就将对应的课的入度-1 */
--_in[edge[u][i]];
if (_in[edge[u][i]] == 0) q.push(edge[u][i]); /* 如果先修课已经上完了,就将当前课加入队列作为可以上的课 */
}
}
for (i = 0; i < numCourses; ++i) { /* 如果把能上的课都上完还有不能上的课,则不能完成学习 */
if (_in[i] != 0) return false;
}
return true;
}
};
2. 1976. 到达目的地的方案数
思路:
dp[k][j]
表示从0->k->n-1的最小距离,利用Folyd算法的思想,更新dp[][]; cnt[][];
数组,获取答案。
class Solution {
#define mod 1000000007
#define ll long long
public:
int countPaths(int n, vector<vector<int>>& roads) {
ll dp[n][n], i, j, k;
ll mat[n][n];
ll cnt[n][n];
ll inf = mod;
inf *= inf;
int roads_size = roads.size();
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
mat[i][j] = inf;
dp[i][j] = inf;
}
}
memset(cnt, 0, sizeof(cnt));
for (i = 0; i < roads_size; ++i) {
int u = roads[i][0];
int v = roads[i][1];
int w = roads[i][2];
mat[u][v] = mat[v][u] = w;
}
cnt[0][0] = 1;
dp[0][0] = 0;
for (i = 1; i < n; ++i) {
for (j = 0; j < n; ++j) {
for (k = 0; k < n; ++k) {
if (dp[i - 1][k] + mat[k][j] < dp[i][j]) { /* 更新最短距离和路劲数目 */
dp[i][j] = dp[i - 1][k] + mat[k][j];
cnt[i][j] = cnt[i - 1][k];
} else if (dp[i - 1][k] + mat[k][j] == dp[i][j]){ /* 路径相同,更新路径数目 */
cnt[i][j] += cnt[i - 1][k];
if (cnt[i][j] >= mod) cnt[i][j] -= mod;
}
}
}
}
// 统计从0经过k到达n-1的路径中最短的距离和对应的路径数
ll dis = inf, ans = 0;
for (k = 0; k < n; ++k) {
if (dis > dp[k][n - 1]) {
dis = dp[k][n - 1];
ans = cnt[k][n - 1];
} else if (dis == dp[k][n - 1]) {
ans += cnt[k][n - 1];
if (ans >= mod) ans -= mod;
}
}
return ans;
}
};
东方欲晓,莫道君行早。