#include <bits/stdc++.h>
using namespace std;
int n, m;
vector<int> fst, snd;
// bottom -> up then true, up -> bottom then false
vector<vector<int>> adj;
vector<int> type;
// determine type
vector<bool> visited, is_selfloop;
vector<vector<int>> locs;
enum Component {
TrivialPath,
SplitPath,
PerfectCycle,
SplitCycle,
ComplexCycle,
SelfLoop,
EmptySelfLoop,
};
// {amt of top, saw path}
pair<int, bool> dfs(int node) {
visited[node] = true;
int top_amt = type[node] == 3;
bool is_path = false;
for (auto v : adj[node]) {
if (visited[v]) continue;
if (v == 0) {
is_path = true;
} else {
auto [tt, ip] = dfs(v);
top_amt += tt;
is_path |= ip;
}
}
return {top_amt, is_path};
}
Component component_type(int node) {
if (is_selfloop[node]) return SelfLoop;
auto [top_amt, is_path] = dfs(node);
if (is_path) {
if (top_amt) return SplitPath;
return TrivialPath;
}
if (top_amt > 1) return ComplexCycle;
if (top_amt) return SplitCycle;
return PerfectCycle;
}
vector<pair<int, int>> drives;
vector<int> auxs;
void trivial_contraction(int node) {
if (node == 0 || type[node] == 3) return;
int a = locs[node][0];
int b = locs[node][1];
if (a == b) return;
bool can_a_pop = snd[a] == 0 || snd[a] == node;
bool can_b_pop = snd[b] == 0 || snd[b] == node;
bool can_a_recv = fst[a] == node && snd[a] == 0;
bool can_b_recv = fst[b] == node && snd[b] == 0;
if (can_b_pop && can_a_recv) {
drives.push_back({b, a});
fst[a] = snd[a] = node;
locs[node] = {a, a};
if (snd[b] == node) {
snd[b] = 0;
trivial_contraction(fst[b]);
} else {
fst[b] = 0;
auxs.push_back(b);
}
} else if (can_a_pop && can_b_recv) {
drives.push_back({a, b});
fst[b] = snd[b] = node;
locs[node] = {b, b};
if (snd[a] == node) {
snd[a] = 0;
trivial_contraction(fst[a]);
} else {
fst[a] = 0;
auxs.push_back(a);
}
}
}
void trivial_component_contraction(int node) {
visited[node] = true;
trivial_contraction(node);
for (auto v : adj[node]) {
if (visited[v]) continue;
trivial_component_contraction(v);
}
}
void perfect_cycle_contraction(int node) {
assert(!auxs.empty());
int aux = auxs.back();
auxs.pop_back();
int a = locs[node][0], b = locs[node][1];
if (snd[a] == node) {
drives.push_back({a, aux});
snd[a] = 0;
fst[aux] = node;
locs[node][0] = aux;
trivial_contraction(fst[a]);
}
if (snd[b] == node) {
drives.push_back({b, aux});
snd[b] = 0;
fst[aux] = node;
locs[node][1] = aux;
trivial_contraction(fst[b]);
}
}
vector<int> component_top_nodes;
void find_top_node_and_contract_ends(int node) {
visited[node] = true;
if (type[node] == 3) component_top_nodes.push_back(node);
trivial_contraction(node);
for (auto v : adj[node]) if (!visited[v]) find_top_node_and_contract_ends(v);
}
void with_top_contraction(int node) {
component_top_nodes.clear();
find_top_node_and_contract_ends(node);
for (auto v : component_top_nodes) {
assert(!auxs.empty());
int aux = auxs.back();
auxs.pop_back();
int a = locs[v][0];
int b = locs[v][1];
locs[v][0] = locs[v][1] = aux;
drives.push_back({a, aux});
drives.push_back({b, aux});
snd[a] = 0, snd[b] = 0;
trivial_contraction(fst[a]);
trivial_contraction(fst[b]);
}
}
void solve() {
cin >> n >> m;
adj.assign(n + 1, {}), type.assign(n + 1, 0), visited.assign(n + 1, false), is_selfloop.assign(n + 1, false);
locs.assign(n + 1, {});
int num_type[7]{};
for (int i = 0; i < m; ++i) {
int a, b;
cin >> a >> b;
if (a) type[a] = 2 * type[a];
if (b) type[b] = 2 * type[b] + 1;
fst.push_back(a), snd.push_back(b);
adj[a].push_back(b), adj[b].push_back(a);
locs[a].push_back(i), locs[b].push_back(i);
if (a == 0 && b == 0) {
num_type[EmptySelfLoop] += 1;
auxs.push_back(i);
}
if (a == b) {
is_selfloop[a] = true;
}
}
// determine all endpoints
vector<pair<Component, int>> sources;
for (int i = 1; i <= n; ++i) {
if (!visited[i]) {
Component cur = component_type(i);
num_type[cur] += 1;
sources.push_back({cur, i});
}
}
int req_moves = num_type[PerfectCycle];
for (int i = 1; i <= n; ++i) {
if (is_selfloop[i]) continue;
req_moves += 1;
if (type[i] == 3) req_moves += 1;
}
// Check if it's possible
num_type[EmptySelfLoop] += num_type[TrivialPath];
num_type[TrivialPath] = 0;
if (num_type[EmptySelfLoop] == 0 &&
(num_type[SplitPath] > 0 || num_type[PerfectCycle] > 0 ||
num_type[SplitCycle] > 0 || num_type[ComplexCycle] > 0)) {
cout << "-1\n";
return;
}
num_type[EmptySelfLoop] += num_type[SplitPath];
if (num_type[ComplexCycle] > 0) {
if (num_type[EmptySelfLoop] < 2) {
cout << "-1\n";
return;
}
}
// do the thing
visited.assign(n + 1, false);
for (auto [type, idx] : sources) {
if (type == TrivialPath) trivial_component_contraction(idx);
}
for (auto [type, idx] : sources) {
if (type == SplitPath || type == SplitCycle) with_top_contraction(idx);
if (type == PerfectCycle) perfect_cycle_contraction(idx);
}
for (auto [type, idx] : sources) {
if (type == ComplexCycle) with_top_contraction(idx);
}
// assert(req_moves == drives.size());
cout << drives.size() << "\n";
for (auto [u, v] : drives) cout << u + 1 << " " << v + 1 << "\n";
}
int main() {
cin.tie(0)->sync_with_stdio(0);
int t = 1;
solve();
}
Compilation message
Main.cpp: In function 'int main()':
Main.cpp:226:9: warning: unused variable 't' [-Wunused-variable]
226 | int t = 1;
| ^
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
0 ms |
344 KB |
Output is correct |
2 |
Correct |
0 ms |
348 KB |
Output is correct |
3 |
Correct |
0 ms |
348 KB |
Output is correct |
4 |
Correct |
0 ms |
348 KB |
Output is correct |
5 |
Correct |
0 ms |
344 KB |
Output is correct |
6 |
Correct |
1 ms |
344 KB |
Output is correct |
7 |
Correct |
0 ms |
348 KB |
Output is correct |
8 |
Correct |
0 ms |
348 KB |
Output is correct |
9 |
Correct |
0 ms |
344 KB |
Output is correct |
10 |
Correct |
0 ms |
348 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Incorrect |
56 ms |
15908 KB |
Output isn't correct |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
348 KB |
Output is correct |
2 |
Correct |
1 ms |
348 KB |
Output is correct |
3 |
Correct |
1 ms |
348 KB |
Output is correct |
4 |
Correct |
1 ms |
604 KB |
Output is correct |
5 |
Correct |
0 ms |
348 KB |
Output is correct |
6 |
Correct |
0 ms |
348 KB |
Output is correct |
7 |
Correct |
1 ms |
600 KB |
Output is correct |
8 |
Correct |
0 ms |
348 KB |
Output is correct |
9 |
Correct |
1 ms |
604 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
348 KB |
Output is correct |
2 |
Correct |
1 ms |
348 KB |
Output is correct |
3 |
Correct |
1 ms |
348 KB |
Output is correct |
4 |
Correct |
1 ms |
604 KB |
Output is correct |
5 |
Correct |
0 ms |
348 KB |
Output is correct |
6 |
Correct |
0 ms |
348 KB |
Output is correct |
7 |
Correct |
1 ms |
600 KB |
Output is correct |
8 |
Correct |
0 ms |
348 KB |
Output is correct |
9 |
Correct |
1 ms |
604 KB |
Output is correct |
10 |
Correct |
128 ms |
29684 KB |
Output is correct |
11 |
Correct |
57 ms |
26044 KB |
Output is correct |
12 |
Correct |
76 ms |
24068 KB |
Output is correct |
13 |
Correct |
133 ms |
28348 KB |
Output is correct |
14 |
Correct |
72 ms |
24628 KB |
Output is correct |
15 |
Correct |
71 ms |
23728 KB |
Output is correct |
16 |
Correct |
133 ms |
29880 KB |
Output is correct |
17 |
Correct |
75 ms |
23608 KB |
Output is correct |
18 |
Correct |
135 ms |
29372 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Incorrect |
0 ms |
348 KB |
Output isn't correct |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
0 ms |
344 KB |
Output is correct |
2 |
Correct |
0 ms |
348 KB |
Output is correct |
3 |
Correct |
0 ms |
348 KB |
Output is correct |
4 |
Correct |
0 ms |
348 KB |
Output is correct |
5 |
Correct |
0 ms |
344 KB |
Output is correct |
6 |
Correct |
1 ms |
344 KB |
Output is correct |
7 |
Correct |
0 ms |
348 KB |
Output is correct |
8 |
Correct |
0 ms |
348 KB |
Output is correct |
9 |
Correct |
0 ms |
344 KB |
Output is correct |
10 |
Correct |
0 ms |
348 KB |
Output is correct |
11 |
Incorrect |
56 ms |
15908 KB |
Output isn't correct |
12 |
Halted |
0 ms |
0 KB |
- |