1. 程式人生 > 其它 >線上視訊教育網站SSM,spring boot(小型教育網站的開發與建設)

線上視訊教育網站SSM,spring boot(小型教育網站的開發與建設)

題目傳送門

一、試題講解

https://www.cnblogs.com/CJYBlog/p/12198894.html

二、拓撲排序完整程式碼

#include <bits/stdc++.h>

using namespace std;
const int N = 5005;         //生物種類上限
const int M = 500005;       //吃與被吃的關係數上限
const int MOD = 80112002;   //最大食物鏈數量模
int n;                      //生物種類
int m;                      //吃與被吃的關係數
int ans;                    //為最大食物鏈數量模上 80112002 的結果
vector<int> edge[N];        //儲存DAG圖的鄰接表
queue<int> q;               //廣搜的佇列
int f[N];                   //每個生物種類的食物鏈最長值
int ind[N];                 //每個生物種類的入度
int out[N];                 //每個生物種類的出度

/**
 總結:
 1、誰向誰有一條有向邊是需要強調的,x->y與 y->x是完全不同的。本題是說x被y吃掉,記錄的是這個關係,
 即x->y有一條有向邊。
 2、需要進行模的題,需要每一步操作結果時,都進行一次MOD操作,防止中間過程資料過大。
 3、獲得的所有食物鏈數量加在一起,再MOD,才是結果。
 4、DAG+廣度優先搜尋= "拓撲排序" !!! !!!!目的:使得在搜到點x時,所有能達到點x的點,已經被搜過了。
 5、拓撲排序思路:把入度為0的入到佇列,然後找到它的所有出邊,對接點入度-1,如果對接點入度為0,則再入佇列。
 6、每一個以當前結點為終止結點的路徑條數,等於上一級的N個結點,每個結點條數的和。
 7、在DAG的廣度搜索中+動態規劃是本題的難點,注意base case的理解。
 8、入度為0的,是第一批入佇列的,它們是食物鏈的底層(草根)。出度為0的是食物鏈的頂層,是老虎,鷹,鯊魚等。
 9、出度是否為0,是判斷是不是再繼續入佇列的條件。
 10、入度為0的所有結點,它們的食物鏈條數和就是答案
 11、與深度優先不同,拓撲排序,需要同時維護出度和入度,出度在錄入資料後,維護不變;入度隨演算法的深入,
 一直在-1,直到為0.
 */

int main() {
    cin >> n >> m;
    //m種關係
    for (int i = 1; i <= m; i++) {
        int x, y;
        cin >> x >> y;          //x被y吃掉
        out[x]++;               //點x的出度+1
        ind[y]++;               //點y的入度+1
        edge[x].push_back(y);   //用鄰接表記錄下食物鏈的關係,x被y吃掉,由x向y引一條有向邊
    }
    //找到所有入度為0的點,放入廣度優先搜尋的佇列
    for (int i = 1; i <= n; i++) if (!ind[i]) q.push(i), f[i] = 1; 
    //f[i]=1:base case,它到它的每個孩子都有一條出邊,就是一條路徑

    //廣度優先搜尋DAG,就是拓撲排序的模板
    while (!q.empty()) {
        int x = q.front();
        q.pop();
        for (int i = 0; i < edge[x].size(); i++) { //遍歷所有出邊
            int y = edge[x][i];                    //目標結點
            f[y] = (f[x] + f[y]) % MOD;         //在計算f[y]之前, f[x]都是計算過的了。
            //對接點入度-1,抹去這條入邊
            ind[y]--;
            //如果入度為0,則入佇列,準備處理它
            if (!ind[y]) q.push(y);
        }
    }
    //遍歷所有結點,如果出度為0,描述
    for (int i = 1; i <= n; i++) if (!out[i]) ans = (ans + f[i]) % MOD;
    cout << ans << endl;
    return 0;
}