AtCoder Beginner Contest 315 - E (toposort)
E - Prerequisites
题意
n 本书,序号 1 ~ n。给定阅读每本书之前必须要看的书的序号。
请你输出任意一种看第一本书所需看书数量最少的方法
思路
利用拓扑序列
先对书之间的制约关系建图,再利用 bfs 找到包含书本 1 的连通块,再对全图进行拓扑排序得到拓扑序列,最后利用这个序列给出包含书本 1 的连通块的书的看书顺序,最后输出即可
本题就是靠你拓扑排序的利用。那么对于任意一本书的看书顺序均可求解。
写的时候遇到一个小问题:sort 函数比较函数利用 lambda 表达式,lambda 表达式值捕获超时,引用捕获嘎嘎快
代码
//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long
using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*
*/
const int maxm = 2e5 + 5, inf = 0x3f3f3f3f, mod = 998244353;
void solve(){
int n;
cin >> n;
int c, p;
vector<int> e[n + 1], in(n + 1, 0);
for(int i = 1; i <= n; ++ i){
cin >> c;
while(c --){
cin >> p;
e[i].push_back(p);
++ in[p];
}
}
//bfs
vector<bool> f(n + 1, false);
queue<int> q;
q.push(1);
while(!q.empty()){
int u = q.front(); q.pop();
for(auto v : e[u]){
if(!f[v]){
f[v] = true;
q.push(v);
}
}
}
//topo
for(int i = 1; i <= n; ++ i){
if(in[i] == 0) q.push(i);
}
vector<int> order(n + 1), t;
while(!q.empty()){
int u = q.front(); q.pop();
t.push_back(u);
for(auto v : e[u]){
-- in[v];
if(in[v] == 0) q.push(v);
}
}
//ans
for(int i = 0; i < n; ++ i){
order[t[i]] = i;
}
vector<int> ans;
for(int i = 2; i <= n; ++ i)
if(f[i]) ans.push_back(i);
sort(ans.begin(), ans.end(), [&](int x, int y){
return order[x] > order[y];
});
int len = ans.size();
for(int i = 0; i < len; ++ i){
cout << ans[i] << " \n"[i == len - 1];
}
return ;
}
signed main(){
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
// cin >> _;
while(_ --){
solve();
}
return 0;
}
本文来自博客园,作者:Qiansui,转载请注明原文链接:https://www.cnblogs.com/Qiansui/p/17644815.html