QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#414615 | #2683. British Menu | shepherd | WA | 1ms | 3832kb | C++20 | 5.9kb | 2024-05-19 12:05:29 | 2024-05-19 12:05:30 |
Judging History
answer
#include <bits/stdc++.h>
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#ifdef LLOCAL
#include "./debug.h"
#else
#define var(...)
#define debugArr(...)
#endif
using namespace std;
#define len(a) static_cast<int>((a).size())
#define present(c, x) (c.find(x) != c.end())
#define printDecimal(d) std::cout << std::setprecision(d) << std::fixed
using ll = long long;
using ull = unsigned long long;
using ld = long double;
constexpr const int iinf = 1e9 + 7;
constexpr const ll inf = 1e18;
static constexpr const ll mod = 1000000007;
template <typename Fun>
class y_combinator_result {
Fun fun_;
public:
template <typename T>
explicit y_combinator_result(T&& fun) : fun_{std::forward<T>(fun)} {}
template <typename... ArgTs>
decltype(auto) operator()(ArgTs&&... args) {
return fun_(std::ref(*this), std::forward<ArgTs>(args)...);
}
};
template <typename Fun>
decltype(auto) y_combinator(Fun&& fun) {
return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}
int main() {
std::ios_base::sync_with_stdio(false);
cin.tie(0);
int n, m;
cin >> n >> m;
vector<vector<int>> graph(n), rev_graph(n);
for (int i = 0; i < m; i++) {
int a, b;
cin >> a >> b;
graph[--a].push_back(--b);
rev_graph[b].push_back(a);
}
// find all scc
vector<bool> visited(n, false);
vector<int> order;
auto dfs1 = y_combinator([&](auto self, int curr) -> void {
visited[curr] = true;
for (const auto& neighbor : graph[curr]) {
if (!visited[neighbor]) self(neighbor);
}
order.push_back(curr);
});
for (int i = 0; i < n; i++) {
if (!visited[i]) {
dfs1(i);
}
}
fill(visited.begin(), visited.end(), false);
reverse(order.begin(), order.end());
vector<int> comp(n, -1);
vector<vector<int>> comps;
int comp_no = 0;
auto dfs2 = y_combinator([&](auto self, int curr) -> void {
visited[curr] = true;
comp[curr] = comp_no;
comps.back().push_back(curr);
for (const auto& neighbor : rev_graph[curr]) {
if (!visited[neighbor]) {
self(neighbor);
}
}
});
for (auto i : order) {
if (!visited[i]) {
comps.emplace_back();
dfs2(i);
sort(comps.back().begin(), comps.back().end());
assert(len(comps.back()) <= 5);
comp_no++;
}
}
vector<vector<pair<int, int>>> comp_edges(comp_no);
map<pair<int, int>, vector<pair<int, int>>> between_comp;
vector<int> p(n);
for (int i = 0; i < n; i++) {
p[i] = lower_bound(comps[comp[i]].begin(), comps[comp[i]].end(), i) -
comps[comp[i]].begin();
}
for (int i = 0; i < n; i++) {
for (const auto& neighbor : graph[i]) {
if (comp[neighbor] == comp[i]) {
comp_edges[comp[i]].emplace_back(p[i], p[neighbor]);
} else {
between_comp[make_pair(comp[i], comp[neighbor])].emplace_back(
p[i], p[neighbor]);
}
}
}
vector<vector<vector<int>>> lookup(
n, vector<vector<int>>(5, vector<int>(5, iinf)));
// do bitmask dp stuff within each scc
for (int ci = 0; ci < comp_no; ci++) {
if (len(comps[ci]) == 1) {
lookup[ci][0][0] = 1;
} else {
vector<vector<int>> sg(len(comps[ci]));
for (const auto& [u, v] : comp_edges[ci]) {
sg[u].push_back(v);
}
for (int i = 0; i < len(comps[ci]); i++) {
vector<vector<bool>> seen(1 << len(comps[ci]),
vector<bool>(len(comps[ci])));
queue<pair<int, int>> q;
seen[1 << i][i] = true;
q.emplace(1 << i, i);
while (!q.empty()) {
auto [mask, pos] = q.front();
q.pop();
lookup[ci][i][pos] =
min(lookup[ci][i][pos], __builtin_popcount(mask));
for (const auto& neighbor : sg[pos]) {
if (!(mask & (1 << neighbor)) &&
!seen[mask | (1 << neighbor)][neighbor]) {
seen[mask | (1 << neighbor)][neighbor] = true;
q.emplace(mask | (1 << neighbor), neighbor);
}
}
}
}
}
}
// compress scc
vector<vector<int>> adj_scc(comp_no);
vector<int> indegree(comp_no);
for (int curr = 0; curr < n; curr++) {
for (const auto& neighbor : graph[curr]) {
int ru = comp[curr], rv = comp[neighbor];
if (ru != rv) {
adj_scc[ru].push_back(rv);
}
}
}
queue<int> q;
for (int i = 0; i < comp_no; i++) {
sort(adj_scc[i].begin(), adj_scc[i].end());
adj_scc[i].erase(unique(begin(adj_scc[i]), end(adj_scc[i])),
adj_scc[i].end());
for (const auto& neighbor : adj_scc[i]) {
indegree[neighbor]++;
}
}
for (int i = 0; i < comp_no; i++) {
if (indegree[i] == 0) {
q.push(i);
}
}
vector<int> top_order;
while (!q.empty()) {
auto curr = q.front();
q.pop();
top_order.push_back(curr);
for (const auto& neighbor : adj_scc[curr]) {
if (--indegree[neighbor] == 0) {
q.push(neighbor);
}
}
}
assert(len(top_order) == comp_no);
int ret = 0;
vector<vector<int>> dp(comp_no, vector<int>(5, -1));
auto solve = y_combinator([&](auto self, int node, int comp_idx) -> int {
if (dp[comp_idx][node] != -1) return dp[comp_idx][node];
for (int i = 0; i < len(comps[comp_idx]); i++) {
dp[comp_idx][node] = max(dp[comp_idx][node], lookup[comp_idx][node][i]);
}
for (const auto& neighbor : adj_scc[comp_idx]) {
for (const auto& [from, to] :
between_comp[make_pair(comp_idx, neighbor)]) {
dp[comp_idx][node] =
max(dp[comp_idx][node],
self(to, neighbor) + lookup[comp_idx][node][from]);
}
}
return dp[comp_idx][node];
});
for (auto ci : top_order) {
for (auto node : comps[ci]) {
ret = max(ret, solve(p[node], ci));
}
}
cout << ret << '\n';
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3624kb
input:
10 6 7 8 4 2 8 6 5 1 4 1 4 5
output:
3
result:
ok single line: '3'
Test #2:
score: 0
Accepted
time: 1ms
memory: 3556kb
input:
10 10 1 3 8 9 6 10 1 2 7 9 10 9 5 1 2 5 8 6 7 8
output:
5
result:
ok single line: '5'
Test #3:
score: 0
Accepted
time: 1ms
memory: 3620kb
input:
10 8 7 6 4 2 10 6 4 5 2 4 3 2 6 10 2 1
output:
4
result:
ok single line: '4'
Test #4:
score: 0
Accepted
time: 0ms
memory: 3620kb
input:
10 19 3 6 9 10 7 9 9 8 8 7 5 6 3 8 6 9 5 9 2 6 6 8 1 4 6 7 6 10 3 9 10 7 4 9 10 8 1 8
output:
6
result:
ok single line: '6'
Test #5:
score: 0
Accepted
time: 0ms
memory: 3584kb
input:
10 19 2 7 8 10 9 8 3 10 8 9 4 5 2 10 1 8 9 6 1 9 4 6 3 2 5 9 5 2 10 7 5 10 7 6 6 9 4 7
output:
8
result:
ok single line: '8'
Test #6:
score: -100
Wrong Answer
time: 1ms
memory: 3832kb
input:
10 18 3 6 2 10 2 5 5 3 4 2 1 5 7 9 10 7 8 6 3 2 4 8 8 9 3 7 7 8 1 4 3 1 5 1 3 9
output:
7
result:
wrong answer 1st lines differ - expected: '9', found: '7'