Skip to content

Commit a8ffa71

Browse files
committed
Tutte matrix matching test
1 parent 3c66602 commit a8ffa71

File tree

2 files changed

+84
-8
lines changed

2 files changed

+84
-8
lines changed

cp-algo/linalg/matrix.hpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <vector>
1010
#include <array>
1111
namespace cp_algo::linalg {
12+
enum gauss_mode {normal, reverse};
1213
template<typename base_t>
1314
struct matrix: valarray_base<matrix<base_t>, vec<base_t>> {
1415
using base = base_t;
@@ -127,17 +128,28 @@ namespace cp_algo::linalg {
127128
}
128129
return *this;
129130
}
130-
131-
enum gauss_mode {normal, reverse};
131+
template<gauss_mode mode = normal>
132+
void eliminate(size_t i, size_t k) {
133+
auto kinv = base(1) / row(i).normalize()[k];
134+
for(size_t j = (mode == normal) * i; j < n(); j++) {
135+
if(j != i) {
136+
row(j).add_scaled(row(i), -row(j).normalize(k) * kinv);
137+
}
138+
}
139+
}
140+
template<gauss_mode mode = normal>
141+
void eliminate(size_t i) {
142+
row(i).normalize();
143+
for(size_t j = (mode == normal) * i; j < n(); j++) {
144+
if(j != i) {
145+
row(j).reduce_by(row(i));
146+
}
147+
}
148+
}
132149
template<gauss_mode mode = normal>
133150
matrix& gauss() {
134151
for(size_t i = 0; i < n(); i++) {
135-
row(i).normalize();
136-
for(size_t j = (mode == normal) * i; j < n(); j++) {
137-
if(j != i) {
138-
row(j).reduce_by(row(i));
139-
}
140-
}
152+
eliminate<mode>(i);
141153
}
142154
return normalize();
143155
}

verify/linalg/tutte.test.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// @brief Matching on General Graph (Tutte matrix)
2+
#define PROBLEM "https://judge.yosupo.jp/problem/general_matching"
3+
#pragma GCC optimize("Ofast,unroll-loops")
4+
#pragma GCC target("tune=native")
5+
#include "cp-algo/linalg/matrix.hpp"
6+
#include "cp-algo/random/rng.hpp"
7+
#include <bits/stdc++.h>
8+
9+
using namespace std;
10+
using namespace cp_algo::math;
11+
using namespace cp_algo::linalg;
12+
using namespace cp_algo::random;
13+
14+
const int mod = 998244353;
15+
using base = modint<mod>;
16+
17+
void solve() {
18+
int n, m;
19+
cin >> n >> m;
20+
matrix<base> T(n);
21+
for(int i = 0; i < m; i++) {
22+
int u, v;
23+
cin >> u >> v;
24+
base x = rng();
25+
T[u][v] += x;
26+
T[v][u] -= x;
27+
}
28+
auto [pivots, free] = matrix(T).echelonize();
29+
matrix<base> B(size(pivots));
30+
for(int i = 0; i < ssize(pivots); i++) {
31+
for(int j = 0; j < ssize(pivots); j++) {
32+
B[i][j] = T[pivots[i]][pivots[j]];
33+
}
34+
}
35+
B = *B.inv();
36+
vector<pair<int, int>> ans;
37+
for(size_t i = 0; i < size(pivots); i++) {
38+
for(size_t j = 0; j < size(pivots); j++) {
39+
if(T[pivots[i]][pivots[j]] != 0 && B[i][j] != 0) {
40+
ans.emplace_back(pivots[i], pivots[j]);
41+
B.eliminate<gauss_mode::reverse>(i, j);
42+
B.eliminate<gauss_mode::reverse>(j, i);
43+
B.normalize();
44+
B[i] *= 0;
45+
B[j] *= 0;
46+
}
47+
}
48+
}
49+
cout << size(ans) << "\n";
50+
for(auto [u, v]: ans) {
51+
cout << u << ' ' << v << "\n";
52+
}
53+
}
54+
55+
signed main() {
56+
//freopen("input.txt", "r", stdin);
57+
ios::sync_with_stdio(0);
58+
cin.tie(0);
59+
int t = 1;
60+
// cin >> t;
61+
while(t--) {
62+
solve();
63+
}
64+
}

0 commit comments

Comments
 (0)