题目描述
在虚拟国度里多了不少 Virtual oier,为了树立对后辈的威信,从第 个 Virtual oier 开始的 oier 们搞起了年功序列的制度。
虚拟国度的创始人 oier Chtholly 感受很是有趣,因而他决定观测 到 这些人,他观测到了一些有趣的现象:虚拟国度里有一些凳子,若是 是 的先辈则 能在 前面获得凳子
Chtholly的观测能够构成 个序列,每一个序列有 个元素 。表示在 有凳子前 必须有凳子。( 是 的前辈)
例如 k = 3 时: ,表示 有凳子前 必须都有凳子, 有凳子前 必须有凳子。
但 Chtholly 年纪大了记忆力未必好,若是第 个序列与前 个序列冲突的话那么就只须要考虑前 个序列就行了。(忽略第 个序列)
Chtholly 但愿知道 到 我的的年功序列的最小字典序。html
输入格式
第一行两个数
接下来 m 行每行第一个数为 ,接下来 个数为此次观测构成的序列node
输出格式
输出 个数构成的最小字典序。web
样例
样例输入
4 3
3 1 2 3
2 4 2
3 3 4 1app样例输出
1 4 2 3svg
样例解释
第三个观测序列与前两个观测序列冲突不考虑,前两个观测序列能够构成 或者 这两个序列,字典序小的为 。spa
数据范围与提示
%的数据,
%的数据,
%的数据, code
这道题看似很难、很复杂,实际上是道简单的拓扑排序。
咱们能够把
~
当作
的入度。(下面也这样说明)
可是咱们只须要把
当作
的入度便可。
由于咱们求到
的时候,前面的
~
必定是求过的
否则不会求到
的
——可是这道题的难点在于冲突的状况orm
咱们先输入第 组的数据 ,把 这组数据 及 之前的数据(没有舍弃的数据) 进行拓扑排序,再判断是否出现了环:xml
正解代码以下:htm
#include <cstdio> #include <cstring> #include <queue> #include <vector> using namespace std; const int MAXN = 1e5 + 5; int N, M, K; int num[MAXN]; vector<int> ans, E[MAXN]; int in[MAXN]; // 每一个人的前辈个数 bool vis[MAXN]; struct node { int numn; node(){} node (int n) { numn = n; } friend bool operator < (node a, node b) { return a.numn > b.numn; } // 字典序排序 }; void toposort() // 拓扑排序 { priority_queue<node> q; for (int i = 1; i <= N; i++) if (in[i] == 0) q.push(node(i)); // 不必定每一个人都有前辈, 因此不须要判断每一个人是否被输入 while (!q.empty()) { int u = q.top().numn; q.pop(); ans.push_back(u); int siz = E[u].size(); for (int i = 0; i < siz; i++) { int v = E[u][i]; --in[v]; if (in[v] == 0) q.push(node(v)); } } } bool check(int u) // 判断是否产生环 { int siz = E[u].size(); for (int i = 0; i < siz; i++) { int v = E[u][i]; if (vis[v]) return 0; vis[v] = 1; if (!check(v)) return 0; } vis[u] = 0; return 1; } int main() { scanf("%d %d", &N, &M); for (int i = 1; i <= M; i++) { scanf("%d", &K); for (int j = 1; j <= K; j++) { scanf("%d", &num[j]); if (j == 1) continue; // 第1我的没有前辈 E[num[j - 1]].push_back(num[j]), ++in[num[j]]; } memset(vis, 0, sizeof(vis)); vis[num[1]] = 1; if (!check(num[1])) // 为何从第1人开始判断, 就留给读者本身思考了 { // 还原 for (int j = 2; j <= K; j++) { // 删除这个入度 --in[num[j]]; E[num[j - 1]].pop_back(); } break; } } toposort(); int siz = ans.size(); for (int i = 0; i < siz; i++) printf("%d ", ans[i]); return 0; }