五月集训(第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;
    }
};
posted @ 2022-06-04 15:27  番茄元  阅读(23)  评论(0)    收藏  举报