This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
#include "simurgh.h"
using namespace std;
class dsu {
public:
vector<int> p;
int n;
dsu(int n): n(n) {
p.resize(n);
for (int i = 0; i < n; ++i) {
p[i] = i;
}
}
inline int find(int x) {
while (x != p[x]) {
x = p[x] = p[p[x]];
}
return x;
}
inline bool unite(int x, int y) {
x = find(x);
y = find(y);
if (x == y) {
return false;
} else {
p[x] = y;
return true;
}
}
};
vector<int> find_roads(int n, vector<int> u, vector<int> v) {
int m = u.size();
vector<int> color(m, -1);
vector<int> tree;
vector<int> ans;
set<int> cur;
auto query = [&](vector<int> edges) {
dsu d(n);
for (auto i : edges) {
d.unite(u[i], v[i]);
}
int more = 0;
for (auto i : tree) {
if (d.unite(u[i], v[i])) {
edges.push_back(i);
more += color[i];
}
}
return count_common_roads(edges) - more;
};
vector<vector<pair<int, int>>> adj(n);
dsu d(n);
for (int i = 0; i < m; ++i) {
if (d.unite(u[i], v[i])) {
adj[u[i]].emplace_back(v[i], i);
adj[v[i]].emplace_back(u[i], i);
tree.push_back(i);
} else {
cur.insert(i);
}
}
vector<int> pv(n, -1);
vector<int> pe(n, -1);
vector<int> depth(n);
function<void(int)> dfs = [&](int x) {
for (auto p : adj[x]) {
if (p.first != pv[x]) {
pv[p.first] = x;
pe[p.first] = p.second;
depth[p.first] = depth[x] + 1;
dfs(p.first);
}
}
};
dfs(0);
auto get_path = [&](int x, int y) {
vector<int> res;
while (x != y) {
if (depth[x] >= depth[y]) {
res.push_back(pe[x]);
x = pv[x];
} else {
res.push_back(pe[y]);
y = pv[y];
}
}
return res;
};
for (int i = 0; i < m; ++i) {
vector<int> path = get_path(u[i], v[i]);
if (path.size() == 1) {
continue;
}
bool all_colored = true;
for (auto j : path) {
if (color[j] == -1) {
all_colored = false;
break;
}
}
if (all_colored) {
continue;
}
path.push_back(i);
int max_common_edges = -n;
for (auto j : path) {
if (color[j] != -1) {
vector<int> edges;
for (auto k : path) {
if (k != j) {
edges.push_back(k);
}
}
max_common_edges = query(edges) + color[j];
break;
}
}
vector<pair<int, int>> all;
for (auto j : path) {
if (color[j] == -1) {
vector<int> edges;
for (auto k : path) {
if (k != j) {
edges.push_back(k);
}
}
int res = query(edges);
max_common_edges = max(max_common_edges, res);
all.emplace_back(j, res);
}
}
for (auto p : all) {
color[p.first] = p.second < max_common_edges;
}
}
for (auto i : tree) {
if (color[i] == -1) {
color[i] = 1;
}
if (color[i]) {
ans.push_back(i);
}
}
function<void(vector<int>, int)> solve = [&](vector<int> e, int common) {
int n = e.size();
if (!common) {
return;
} else if (common == n) {
for (auto i : e) {
ans.push_back(i);
}
} else {
vector<int> left(e.begin(), e.begin() + (n >> 1));
vector<int> right(e.begin() + (n >> 1), e.end());
int common_left = query(left);
int common_right = common - common_left;
solve(left, common_left);
solve(right, common_right);
}
};
for (int i = 0; i < n; ++i) {
vector<int> useful;
for (auto j : cur) {
if (u[j] == i || v[j] == i) {
useful.push_back(j);
}
}
if (!useful.empty()) {
for (auto j : useful) {
cur.erase(j);
}
solve(useful, query(useful));
}
}
sort(ans.begin(), ans.end());
return ans;
}
# | 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... |