年功序列 題解
阿新 • • 發佈:2020-08-18
分析
此題如果沒有Chtholly年紀大了記憶力未必好,如果第\(i\)個序列與前\(i−1\)個序列衝突的話那麼就只需要考慮前\(i−1\)個序列就好了的限制,就會是一道\(topsort\)的板題。
判斷是否有環
建立鄰接表
輸入時前後相連,建立鄰接表,如果無環則會形成一個長鏈。
判環
從\(x[1]\)開始判斷,如果有環,就直接退出迴圈。
具體方法
bool check(int x) { for (int i = 0; i < G[x].size(); i++) { if (vis[G[x][i]] == 1) {//如果已經訪問過,就說明有環存在 return 0; } vis[G[x][i]] = 1; if (check(G[x][i]) == 0) { vis[G[x][i]] = 0;//重置 return 0; } } vis[x] = 0;//重置 return 1; }
實現
#include <cstring> #include <queue> #include <vector> #include <cstdio> #include <iostream> #include <algorithm> using namespace std; const int MAXN = 1e5 + 5; int n, m, x[MAXN], deg[MAXN], ans[MAXN], cnt; bool vis[MAXN]; vector<int> G[MAXN]; priority_queue<int, vector<int>, greater<int> > q; bool check(int x) { for (int i = 0; i < G[x].size(); i++) { if (vis[G[x][i]] == 1) { return 0; } vis[G[x][i]] = 1; if (check(G[x][i]) == 0) { vis[G[x][i]] = 0; return 0; } } vis[x] = 0; return 1; } void topsort() { for (int i = 1; i <= n; i++) { if (deg[i] == 0) { q.push(i); } } while (q.size()) { int u = q.top(); q.pop(); ans[++cnt] = u; for (int i = 0; i < G[u].size(); i++) { deg[G[u][i]] --; if (deg[G[u][i]] == 0) { q.push(G[u][i]); } } } for (int i = 1; i <= n; i++) { printf ("%d ", ans[i]); } } int main() { scanf ("%d %d", &n, &m); while (m --) { int k; scanf ("%d", &k); memset(vis, 0, sizeof(vis)); for (int i = 1; i <= k; i++) { scanf ("%d", &x[i]); if (i != 1) { deg[x[i]] ++; G[x[i - 1]].push_back(x[i]); } } vis[x[1]] = 1; if (! check(x[1])) { for (int i = 2; i <= k; i++) { G[x[i - 1]].pop_back(); deg[x[i]] --; } break; } } topsort(); return 0; }