QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#839324 | #873. Königsberg Bridges | ohwphil | WA | 571ms | 169800kb | C++17 | 5.9kb | 2025-01-01 17:05:12 | 2025-01-01 17:05:12 |
Judging History
answer
#include <bits/stdc++.h>
#include <array>
using namespace std;
typedef long long ll;
// DFS Tree
// Finds bridges, articulation points, and biconnected components
struct DFSTree {
// size of graph
int N;
vector<vector<int>> adj, tree_children, back_edges;
vector<int> tree_parent;
vector<int> depth, dp;
vector<pair<int, int>> bridges;
vector<int> articulation_points;
vector<vector<pair<int, int>>> biconnected_components;
stack<pair<int, int>> edge_stack;
DFSTree() { DFSTree(0); }
DFSTree(int _N) : N(_N), adj(_N + 1), tree_children(_N + 1), back_edges(_N + 1), tree_parent(_N + 1, -1), depth(_N + 1, -1), dp(_N + 1) {}
void add_edge(int u, int v) {
adj[u].push_back(v);
adj[v].push_back(u);
}
void dfs(int curr_node, int curr_depth = 0) {
depth[curr_node] = curr_depth;
int cnt = 0;
for (int next_node : adj[curr_node]) {
if (next_node == tree_parent[curr_node]) {
continue;
}
if (depth[next_node] == -1) {
edge_stack.push(make_pair(min(curr_node, next_node), max(curr_node, next_node)));
tree_children[curr_node].push_back(next_node);
tree_parent[next_node] = curr_node;
int curr_dp = dp[curr_node];
dfs(next_node, curr_depth + 1);
dp[curr_node] += dp[next_node];
if (dp[curr_node] == curr_dp) {
++cnt;
// separate biconnected component
vector<pair<int, int>> component;
auto reference_pair = make_pair(min(curr_node, next_node), max(curr_node, next_node));
while (true) {
auto edge = edge_stack.top();
edge_stack.pop();
component.push_back(edge);
if (edge == reference_pair) {
break;
}
}
biconnected_components.push_back(component);
}
}
else if (depth[next_node] < depth[curr_node]) {
edge_stack.push(make_pair(min(curr_node, next_node), max(curr_node, next_node)));
back_edges[curr_node].push_back(next_node);
++dp[next_node];
--dp[curr_node];
}
}
if (tree_parent[curr_node] != -1 && dp[curr_node] == 0) {
bridges.push_back({min(curr_node, tree_parent[curr_node]), max(curr_node, tree_parent[curr_node])});
}
if ((tree_parent[curr_node] == -1 && cnt >= 2) || (tree_parent[curr_node] != -1 && cnt >= 1)) {
articulation_points.push_back(curr_node);
}
}
void compute() {
for (int i = 1; i <= N; i++) {
if (depth[i] == -1) {
dfs(i, 0);
}
}
sort(bridges.begin(), bridges.end());
sort(articulation_points.begin(), articulation_points.end());
}
};
// Disjoint set union
struct DSU {
// size of graph
int N;
vector<int> rank;
DSU() { DSU(0); }
DSU(int _N) : N(_N), rank(_N + 1, -1) {}
int get_parent(int node) {
if (rank[node] < 0) {
return node;
}
return rank[node] = get_parent(rank[node]);
}
void merge(int node1, int node2) {
node1 = get_parent(node1);
node2 = get_parent(node2);
if (node1 == node2) return;
if (-rank[node1] < -rank[node2]) swap(node1, node2);
rank[node1] += rank[node2];
rank[node2] = node1;
}
};
int N, M;
DFSTree tree;
DSU dsu;
vector<int> bridge_dp;
set<pair<int, int>> multiple_edges;
map<pair<int, int>, int> counter;
int ans;
int dfs_dp(int node) {
// bridge_dp[node] = (tree.tree_parent[node] != -1 && tree.dp[node] == 0);
// if (tree.tree_parent[node] != -1 && multiple_edges.find({min(node, tree.tree_parent[node]), max(node, tree.tree_parent[node])}) != multiple_edges.end()) {
// bridge_dp[node] = 0;
// }
vector<int> values;
for (auto child : tree.tree_children[node]) {
int curr_val = dfs_dp(child);
if (multiple_edges.find({min(node, child), max(node, child)}) == multiple_edges.end() && tree.dp[child] == 0) {
++curr_val;
}
values.push_back(curr_val);
}
sort(values.begin(), values.end());
if (values.size() == 0) {
return 0;
}
if (values.size() == 1) {
ans = max(values[0], ans);
}
if (values.size() >= 2) {
ans = max(values[values.size() - 2] + values[values.size() - 1], ans);
}
return values[values.size() - 1];
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> N >> M;
bridge_dp.resize(N + 1);
dsu = DSU(N);
tree = DFSTree(N);
for (int i = 0; i < M; ++i) {
int u, v;
cin >> u >> v;
if (u == v) continue;
++u; ++v;
if (u > v) swap(u, v);
// tree.add_edge(u, v);
// edge_sets.insert({u, v});
++counter[{u, v}];
if (counter[{u, v}] == 2) {
multiple_edges.insert({u, v});
}
}
for (auto [p, c] : counter) {
auto [u, v] = p;
tree.add_edge(u, v);
dsu.merge(u, v);
}
vector<int> parents;
for (int i = 1; i <= N; ++i) {
parents.push_back(dsu.get_parent(i));
}
sort(parents.begin(), parents.end());
parents.erase(unique(parents.begin(), parents.end()), parents.end());
for (int i = 0; i < parents.size() - 1; ++i) {
tree.add_edge(min(parents[i], parents[i + 1]), max(parents[i], parents[i + 1]));
}
tree.compute();
dfs_dp(1);
cout << ans << "\n";
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3496kb
input:
4 3 0 1 1 2 2 0
output:
1
result:
ok 1 number(s): "1"
Test #2:
score: 0
Accepted
time: 0ms
memory: 3844kb
input:
4 2 0 1 1 2
output:
3
result:
ok 1 number(s): "3"
Test #3:
score: -100
Wrong Answer
time: 571ms
memory: 169800kb
input:
266912 867557 0 31522 0 174162 0 4209 1 58647 1 5722 1 24762 1 258525 1 148028 1 72989 1 170812 1 260494 1 86533 1 212481 2 143457 2 47080 2 72841 2 113512 2 64754 2 231454 3 220536 3 97144 3 183508 3 177546 3 149060 3 140197 3 87427 3 169096 4 132318 4 67337 4 23014 4 34254 4 11851 4 12558 4 49756 ...
output:
374
result:
wrong answer 1st numbers differ - expected: '380', found: '374'