Skip to content

Commit fec4131

Browse files
committed
MST + test
1 parent f91796a commit fec4131

File tree

5 files changed

+98
-11
lines changed

5 files changed

+98
-11
lines changed

cp-algo/data_structures/dsu.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifndef CP_ALGO_DATA_STRUCTURES_DSU_HPP
2+
#define CP_ALGO_DATA_STRUCTURES_DSU_HPP
3+
#include <numeric>
4+
#include <vector>
5+
namespace cp_algo::data_structures {
6+
struct disjoint_set_union {
7+
disjoint_set_union (int n): par(n) {
8+
std::iota(begin(par), end(par), 0);
9+
}
10+
int get(int v) {
11+
return v == par[v] ? v : par[v] = get(par[v]);
12+
}
13+
bool uni(int a, int b) {
14+
a = get(a);
15+
b = get(b);
16+
par[a] = b;
17+
return a != b;
18+
}
19+
private:
20+
std::vector<int> par;
21+
};
22+
using dsu = disjoint_set_union;
23+
}
24+
#endif // CP_ALGO_DATA_STRUCTURES_DSU_HPP

cp-algo/graph/base.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,19 @@ namespace cp_algo::graph {
3535
call_adjacent(v, callback, [](){return false;});
3636
}
3737
void call_edges(auto &&callback) const {
38-
for(node_index v: nodes_view()) {
39-
call_adjacent(v, [&](edge_index e) {callback(v, e);});
38+
for(edge_index e: edges_view()) {
39+
callback(e);
4040
}
4141
}
4242
auto nodes_view() const {
4343
return std::views::iota(0, n());
4444
}
45+
auto edges_view() const {
46+
return std::views::filter(
47+
std::views::iota(0, 2 * m()),
48+
[](edge_index e) {return !(e % 2);}
49+
);
50+
}
4551
auto const& incidence_lists() const {return _adj;}
4652
edge_t const& edge(edge_index e) const {return edges[e];}
4753
node_index n() const {return _adj.size();}

cp-algo/graph/euler.hpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@ namespace cp_algo::graph {
1010
std::vector<int> deg(g.n());
1111
constexpr bool undirected = graph::undirected;
1212
int res = 0;
13-
g.call_edges([&](int u, int e) {
13+
g.call_edges([&](edge_index e) {
14+
int u = g.edge(e ^ 1).to;
15+
int v = g.edge(e).to;
1416
res = u;
15-
if constexpr (undirected) {
16-
deg[u] ^= 1;
17-
} else {
18-
deg[u]++;
19-
deg[g.edge(e).to]--;
20-
}
17+
deg[u]++;
18+
deg[v]--;
2119
});
20+
if constexpr (undirected) {
21+
for(auto &it: deg) {
22+
it = bool(it % 2);
23+
}
24+
}
2225
auto nodes = g.nodes_view();
2326
auto is_start = [&](int v) {return deg[v] > 0;};
2427
auto starts = std::ranges::count_if(nodes, is_start);
@@ -42,8 +45,7 @@ namespace cp_algo::graph {
4245
int e = adj.data[std::exchange(head[v], adj.next[head[v]])];
4346
if(!used[e / 2]) {
4447
used[e / 2] = 1;
45-
int u = g.edge(e).to;
46-
self(self, u);
48+
self(self, g.edge(e).to);
4749
trail.push_back(e);
4850
}
4951
}

cp-algo/graph/mst.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#ifndef CP_ALGO_GRAPH_MST_HPP
2+
#define CP_ALGO_GRAPH_MST_HPP
3+
#include "base.hpp"
4+
#include "../data_structures/dsu.hpp"
5+
#include <algorithm>
6+
namespace cp_algo::graph {
7+
template<weighted_edge_type edge_t>
8+
auto mst(graph<undirected, edge_t> const& g) {
9+
std::vector<std::pair<int64_t, edge_index>> edges;
10+
g.call_edges([&](edge_index e) {
11+
edges.emplace_back(g.edge(e).w, e);
12+
});
13+
std::ranges::sort(edges);
14+
data_structures::dsu me(g.n());
15+
int64_t total = 0;
16+
std::vector<edge_index> mst;
17+
for(auto [w, e]: edges) {
18+
if(me.uni(g.edge(e ^ 1).to, g.edge(e).to)) {
19+
total += w;
20+
mst.push_back(e);
21+
}
22+
}
23+
return std::pair{total, mst};
24+
}
25+
}
26+
#endif // CP_ALGO_GRAPH_MST_HPP

verify/graph/mst.test.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// @brief Minimum Spanning Tree
2+
#define PROBLEM "https://judge.yosupo.jp/problem/minimum_spanning_tree"
3+
#pragma GCC optimize("Ofast,unroll-loops")
4+
#include "cp-algo/graph/mst.hpp"
5+
#include <bits/stdc++.h>
6+
7+
using namespace std;
8+
using namespace cp_algo::graph;
9+
10+
void solve() {
11+
int n, m;
12+
cin >> n >> m;
13+
graph<undirected, weighted_edge> g(n);
14+
g.read_edges(m);
15+
auto [X, E] = mst(g);
16+
cout << X << "\n";
17+
for(int e: E) {cout << e / 2 << " ";}
18+
}
19+
20+
signed main() {
21+
//freopen("input.txt", "r", stdin);
22+
ios::sync_with_stdio(0);
23+
cin.tie(0);
24+
int t = 1;
25+
//cin >> t;
26+
while(t--) {
27+
solve();
28+
}
29+
}

0 commit comments

Comments
 (0)