#include "islands.h"
#include <iostream>
#include <map>
#include <variant>
#include <vector>
std::variant<bool, std::vector<int>> find_journey_connected(int N, int M, std::vector<int> U, std::vector<int> V, std::vector<int> original_labels);
std::variant<bool, std::vector<int>> find_journey(int N, int M, std::vector<int> U, std::vector<int> V) {
std::vector<std::vector<int>> canoesfrom(N);
for (int i = 0; i < M; ++i) canoesfrom[U[i]].push_back(i);
std::vector<bool> seen(N);
std::vector<int> stack = {0};
while (!stack.empty()) {
int node = stack.back();
stack.pop_back();
if (seen[node]) continue;
seen[node] = true;
for (int i : canoesfrom[node]) {
stack.push_back(V[i]);
}
}
std::vector<int> newu, newv, original_labels;
int newm = 0;
for (int i = 0; i < N; ++i) {
if (!seen[i]) continue;
for (int out : canoesfrom[i]) {
newu.push_back(U[out]);
newv.push_back(V[out]);
original_labels.push_back(out);
++newm;
}
}
return find_journey_connected(N, newm, newu, newv, original_labels);
}
std::variant<bool, std::vector<int>> find_journey_connected(int N, int M, std::vector<int> U, std::vector<int> V, std::vector<int> original_labels) {
std::vector<std::vector<int>> out(N), in(N);
for (int i = 0; i < M; ++i) out[U[i]].push_back(i), in[V[i]].push_back(i);
U.push_back(-1);
V.push_back(0); // dummy edge to source
// stage 1: find any loop
std::vector<int> is_marked(N);
std::vector<int> seen(N);
std::vector<int> inpath(N);
std::vector<int> path;
std::vector<int> stack = {M};
bool foundcyclestagei = false;
while (!stack.empty()) {
int canoe = stack.back();
stack.pop_back();
if (canoe == -1) {
inpath[V[path.back()]] = false;
path.pop_back();
continue;
}
path.push_back(canoe);
int node = V[canoe];
if (seen[node]) {
if (!inpath[node]) continue;
foundcyclestagei = true;
is_marked[node] = true;
while (U[path.back()] != node) {
is_marked[U[path.back()]] = true;
path.pop_back();
}
path.pop_back();
break;
}
seen[node] = true;
inpath[node] = true;
for (int to : out[node]) {
stack.push_back(-1);
stack.push_back(to);
}
}
if (!foundcyclestagei) return false;
// Stage 2: check multiple reachability to marked nodes
std::vector<int> canreach(N, false);
stack.clear();
for (int i = 0; i < N; ++i) {
if (is_marked[i]) stack.push_back(i);
}
while (!stack.empty()) {
int node = stack.back();
stack.pop_back();
if (canreach[node]) continue;
canreach[node] = true;
for (int revedge : in[node]) {
stack.push_back(U[revedge]);
}
}
bool multiplereachabilitystageii = false;
for (int i = 0; i < N; ++i) {
if (is_marked[i] && i != V[path.back()]) continue;
int canoecnt = 0;
for (int to : out[i]) {
canoecnt += canreach[V[to]];
}
multiplereachabilitystageii |= (canoecnt >= 2);
}
if (multiplereachabilitystageii) return true;
// Stage 3: we don't have multiple reachability, but let's look for a second cycle
bool foundcyclestageiii = false;
stack = {M};
seen = std::vector<int>(N, false);
while (!stack.empty()) {
int canoe = stack.back();
stack.pop_back();
int node = V[canoe];
if (is_marked[node] && node != path.back()) continue; // avoid refinding the same cycle
if (seen[node]) {
foundcyclestageiii = true;
break;
}
seen[node] = true;
for (int to : out[node]) {
stack.push_back(to);
}
}
return foundcyclestageiii;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |