分析:
此題就是求一個有向圖中是否存在環。 如存在環則輸出"Wrong", 若不存在環, 說明課程安排的合理,輸出"Correct"。
題中的提示說的已經十分清楚了。
總的來說就是:
① 找出入度為0的點(說明該點沒有前驅),把該點放入集合T中。 把所有從該點出發的邊都刪除;
② 遍歷剩余的點, 找出入度為0 的點, 重復①操作。
③直到不存在入度為0的點。 結束。如果此時集合T中包含所有的點, 那麼該圖不存在環, 否則存在環。
注意:1、執行操作①時, 在刪除邊時(u, v),同時更新與其相關點的入度(du[v]--);
2、 在執行操作②時, 需要遍歷所有點, 點少的時候可行, 點多的話很容易超時。 所以題目的提示中告訴了一個好辦法就是: 執行操作①更新相關點的入度時直接判斷一下是否為0, 若為零則入隊列。 這樣會省很多時間。
如下圖例子:
開始點1入度為0, 點1加入集合T, 刪除從1出發的邊; 更新相關點的入度, 點2、3的入度都變為0了 , 2、3入隊列;
再依次對點2、3進行①操作, 2、3加入T, 刪除邊(2, 4), (3, 4), 此時沒有其他點入度為0了, 結束操作, T中未包含所有點, 說明該圖中有環;
#include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<vector> #include<queue> using namespace std; int t, n, m, sum, du[100005]; vector<int> vec[100005]; int ac() { queue<int> q; for(int i = 1; i <= n; i++)//遍歷一邊所有點, 把入度為0的點,全加入隊列q中 { if(du[i] == 0) q.push(i); } while(!q.empty()) { int tem = q.front();//在隊列中取出一個入度為0的點 q.pop(); sum++; //把所有從tem出發的邊(tem, v)刪除並更新du[], for(int i = 0; i < vec[tem].size(); i++) { du[vec[tem][i]]--; if(du[vec[tem][i]] == 0)//若點vec[tem][i]入度更新後為0, 則入隊列 q.push(vec[tem][i]); } vec[tem].clear(); } if(sum == n) return 1; else return 0; } int main() { cin >> t; while(t--) { scanf("%d%d", &n, &m); //用vec[]來存邊 for(int i = 1; i <= n; i++) vec[i].clear(); memset(du, 0, sizeof(du));//初始化入度, 置為0; for(int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); vec[x].push_back(y); // 加入邊 du[y]++; //記錄入度 } sum = 0; int ans = ac(); if(ans == 1) printf("Correct\n"); else printf("Wrong\n"); } return 0; }
分析:
和上一道差不多, 只是多了一項就是記錄每個點的病毒數。 每個點的病毒數 = 自身病毒數 + 所有能夠達到它的節點病毒數之和( 就是所有它前驅點的病毒數的和)。
#include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<vector> #include<queue> using namespace std; const int mod = 142857; int n, m, k, sum, virus[100005], du[100005]; vector<int> vec[100005]; void ac() { queue<int> q; for(int i = 1; i <= n; i++) { if(du[i] == 0) q.push(i); } while(!q.empty()) { int tmp = q.front(); q.pop(); sum = (sum + virus[tmp]) % mod; //把所有前驅點為 tmp 的點的病毒數都加上 tmp的病毒數 for(int i = 0; i < vec[tmp].size(); i++) { int b = vec[tmp][i]; virus[b] = (virus[tmp] + virus[b]) % mod;// 此處也一定要取模, du[b]--; if(du[b] == 0) q.push(b); } vec[tmp].clear(); } } int main() { while(scanf("%d%d%d", &n, &m, &k) != EOF) { memset(virus, 0, sizeof(virus)); memset(du, 0, sizeof(du)); for(int i = 1; i <= n; i++) vec[i].clear(); for(int i = 1; i <= k; i++) { int x; scanf("%d", &x); virus[x]++; } for(int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); vec[x].push_back(y); du[y]++; } sum = 0; ac(); printf("%d\n", sum); } return 0; }