Skip to content

Commit 7c3e3dc

Browse files
committed
✅ test(mcmf): update tests
1 parent 75d9be3 commit 7c3e3dc

27 files changed

+452
-279
lines changed

Diff for: _fixtures/codeforces/0277/E/data.json

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
[
2+
{
3+
"input": [
4+
[
5+
[0, 0],
6+
[1, 0],
7+
[2, 1]
8+
]
9+
],
10+
"answer": 3.6502815398728847
11+
},
12+
{
13+
"input": [
14+
[
15+
[0, 0],
16+
[1, 0],
17+
[2, 1],
18+
[2, 0]
19+
]
20+
],
21+
"answer": -1
22+
},
23+
{
24+
"input": [
25+
[
26+
[-1000, -1000],
27+
[1000, 1000]
28+
]
29+
],
30+
"answer": 2828.42712474619
31+
},
32+
{
33+
"input": [
34+
[
35+
[890, -179],
36+
[-991, -555],
37+
[874, 452],
38+
[352, 312],
39+
[60, -743],
40+
[-363, 607],
41+
[164, -961],
42+
[-607, 580],
43+
[-474, 791],
44+
[-749, -472],
45+
[-947, 739],
46+
[555, -719],
47+
[479, 269],
48+
[254, -201],
49+
[-417, -352],
50+
[-596, 592],
51+
[-715, 433],
52+
[319, 968],
53+
[-316, -126],
54+
[915, 548]
55+
]
56+
],
57+
"answer": 7451.922614948992
58+
},
59+
{
60+
"input": [
61+
[
62+
[44, 339],
63+
[226, 988],
64+
[588, 298],
65+
[251, -852],
66+
[585, 551],
67+
[-916, 814],
68+
[455, 412],
69+
[272, 261],
70+
[-909, -133],
71+
[466, -923],
72+
[928, -374],
73+
[-188, 425],
74+
[598, 189],
75+
[-642, -84],
76+
[-110, 8],
77+
[-352, 866],
78+
[-766, -803],
79+
[-593, 823],
80+
[-786, 815],
81+
82+
[-963, 943]
83+
]
84+
],
85+
"answer": 7938.614004106956
86+
}
87+
]

Diff for: packages/mcmf/README.md

+114-52
Original file line numberDiff line numberDiff line change
@@ -76,98 +76,160 @@ The **MCMF** algorithm is an algorithm for solving network flow problems.
7676

7777
## Usage
7878

79-
* Codeforces contest 1082 Problem G (https://codeforces.com/contest/1082/problem/G):
79+
* Codeforces contest 0277 Problem E (https://codeforces.com/contest/277/problem/E):
8080

8181
```typescript
8282
import { createMcmf } from '@algorithm.ts/mcmf'
8383

8484
const mcmf = createMcmf()
85+
export function solveCodeforces0277E(coordinates: Array<[x: number, y: number]>): number {
86+
const N: number = coordinates.length
8587

86-
// The implementation of `io` is omitted.
87-
function solve(io: any): number {
88-
const [n, m] = io.readIntegersOfLine()
88+
const vertexes: IVertex[] = coordinates
89+
.map(([x, y]) => ({ x, y }))
90+
.sort((p, q) => {
91+
if (p.y === q.y) return p.x - q.x
92+
return q.y - p.y
93+
})
94+
95+
const source = 0
96+
const target: number = N * 2 + 1
97+
mcmf.init(source, target, N * 2 + 2)
98+
99+
for (let i = 0; i < N; ++i) {
100+
mcmf.addEdge(source, i + 1, 2, 0)
101+
mcmf.addEdge(N + i + 1, target, 1, 0)
102+
for (let j = i + 1; j < N; ++j) {
103+
if (vertexes[i].y === vertexes[j].y) continue
104+
mcmf.addEdge(i + 1, N + j + 1, 1, dist(vertexes[i], vertexes[j]))
105+
}
106+
}
107+
108+
const [mincost, maxflow] = mcmf.minCostMaxFlow()
109+
const answer = maxflow === N - 1 ? mincost : -1
110+
return answer
111+
}
112+
113+
function dist(p: IVertex, q: IVertex): number {
114+
const d = (p.x - q.x) * (p.x - q.x) + (p.y - q.y) * (p.y - q.y)
115+
return Math.sqrt(d)
116+
}
117+
118+
interface IVertex {
119+
x: number
120+
y: number
121+
}
122+
```
123+
124+
125+
* A solution for Codeforces contest 1082 Problem G (https://codeforces.com/contest/1082/problem/G):
126+
127+
```typescript
128+
import { createMcmf } from '@algorithm.ts/mcmf'
129+
130+
const mcmf = createMcmf()
131+
export function solveCodeforces1082G(
132+
nodes: number[],
133+
edges: Array<[u: number, v: number, weight: number]>,
134+
): number {
135+
const n: number = nodes.length
136+
const m: number = edges.length
89137

90138
const source = 0
91139
const target: number = n + m + 1
92-
mcmf.init(source, target, n + m + 2, n + m * 3)
140+
mcmf.init(source, target, n + m + 2)
93141

94-
const nodes: number[] = io.readIntegersOfLine()
95142
for (let i = 0; i < n; ++i) {
96143
const weight: number = nodes[i]
97-
mcmf.addEdge(i + 1, target, weight, 1)
144+
mcmf.addEdge(i + 1, target, weight, 0)
98145
}
99146

100147
let answer = 0
101-
for (let i = 1; i <= m; ++i) {
102-
const [u, v, weight] = io.readIntegersOfLine()
148+
for (let i = 0; i < m; ++i) {
149+
const [u, v, weight] = edges[i]
103150
const x = n + i
104151
answer += weight
105-
mcmf.addEdge(source, x, weight, 1)
106-
mcmf.addEdge(x, u, Number.MAX_SAFE_INTEGER, 1)
107-
mcmf.addEdge(x, v, Number.MAX_SAFE_INTEGER, 1)
152+
mcmf.addEdge(source, x, weight, 0)
153+
mcmf.addEdge(x, u, Number.MAX_SAFE_INTEGER, 0)
154+
mcmf.addEdge(x, v, Number.MAX_SAFE_INTEGER, 0)
108155
}
109-
110-
const [mincost, maxflow] = mcmf.minCostMaxFlow()
111-
answer -= maxflow
156+
answer -= mcmf.maxFlow()
112157
return answer
113158
}
114159
```
115160

116-
* Codeforces contest 0277 Problem E (https://codeforces.com/contest/277/problem/E):
161+
* A solution for leetcode "Maximum Students Taking Exam" (https://leetcode.com/problems/maximum-students-taking-exam/):
117162

118163
```typescript
119164
import { createMcmf } from '@algorithm.ts/mcmf'
120165

121-
const mcmf = createMcmf()
166+
export function maxStudents(seats: string[][]): number {
167+
const R: number = seats.length
168+
if (R <= 0) return 0
122169

123-
// The implementation of `io` is omitted.
124-
function solve(io: any): number {
125-
const [N] = io.readIntegersOfLine()
170+
const C: number = seats[0].length
171+
if (C <= 0) return 0
126172

127-
const vertexes: Vertex[] = new Array(N)
128-
for (let i = 0; i < N; ++i) {
129-
const [x, y] = io.readIntegersOfLine()
130-
vertexes[i] = { x, y }
131-
}
132-
vertexes.sort((p, q) => {
133-
if (p.y === q.y) return p.x - q.x
134-
return q.y - p.y
135-
})
136-
137-
const source = 0
138-
const target: number = N * 2 + 1
139-
mcmf.init(source, target, N * 2 + 2, N * N + 2 * N)
173+
let total = 0
174+
const seatCodes: number[][] = new Array(R)
175+
for (let r = 0; r < R; ++r) seatCodes[r] = new Array(C).fill(-1)
140176

141-
for (let i = 0; i < N; ++i) {
142-
mcmf.addEdge(source, i + 1, 2, 0)
143-
mcmf.addEdge(N + i + 1, target, 1, 0)
144-
for (let j = i + 1; j < N; ++j) {
145-
if (vertexes[i].y === vertexes[j].y) continue
146-
mcmf.addEdge(i + 1, N + j + 1, 1, dist(vertexes[i], vertexes[j]))
177+
for (let r = 0; r < R; ++r) {
178+
for (let c = 0; c < C; ++c) {
179+
if (seats[r][c] === '.') seatCodes[r][c] = total++
147180
}
148181
}
149182

150-
const [mincost, maxflow] = mcmf.minCostMaxFlow()
151-
const answer = maxflow === N - 1 ? mincost : -1
152-
return answer
153-
}
154-
155-
function dist(p: Vertex, q: Vertex): number {
156-
const d = (p.x - q.x) * (p.x - q.x) + (p.y - q.y) * (p.y - q.y)
157-
return Math.sqrt(d)
158-
}
183+
if (total <= 0) return 0
184+
if (total === 1) return 1
185+
186+
const source: number = total * 2
187+
const target: number = source + 1
188+
const mcmf = createMcmf()
189+
mcmf.init(source, target, target + 1)
190+
191+
for (let r = 0; r < R; ++r) {
192+
for (let c = 0; c < C; ++c) {
193+
const u: number = seatCodes[r][c]
194+
if (u > -1) {
195+
mcmf.addEdge(source, u, 1, 0)
196+
mcmf.addEdge(u + total, target, 1, 0)
197+
if (r > 0) {
198+
// Check upper left
199+
if (c > 0 && seatCodes[r - 1][c - 1] > -1) {
200+
const v: number = seatCodes[r - 1][c - 1]
201+
mcmf.addEdge(u, v + total, 1, 0)
202+
mcmf.addEdge(v, u + total, 1, 0)
203+
}
204+
205+
// Check upper right
206+
if (c + 1 < C && seatCodes[r - 1][c + 1] > -1) {
207+
const v: number = seatCodes[r - 1][c + 1]
208+
mcmf.addEdge(u, v + total, 1, 0)
209+
mcmf.addEdge(v, u + total, 1, 0)
210+
}
211+
}
212+
213+
// Check left
214+
if (c > 0 && seatCodes[r][c - 1] > -1) {
215+
const v: number = seatCodes[r][c - 1]
216+
mcmf.addEdge(u, v + total, 1, 0)
217+
mcmf.addEdge(v, u + total, 1, 0)
218+
}
219+
}
220+
}
221+
}
159222

160-
interface Vertex {
161-
x: number
162-
y: number
223+
const totalPaired: number = mcmf.maxFlow() / 2
224+
return total - totalPaired
163225
}
164226
```
165227

166228
## Related
167229

168230

169231
* [@algorithm.ts/dinic](https://github.com/guanghechen/algorithm.ts/tree/main/packages/dinic)
170-
* [@algorithm.ts/isap](https://github.com/guanghechen/algorithm.ts/tree/main/packages/isap)
232+
* [@algorithm.ts/mcmf](https://github.com/guanghechen/algorithm.ts/tree/main/packages/mcmf)
171233
* [网络流 24 题](https://me.guanghechen.com/post/algorithm/graph/network-flow/24-problems/)
172234
* [网络流基础之最大权闭合图](https://me.guanghechen.com/post/algorithm/graph/network-flow/%E6%9C%80%E5%A4%A7%E6%9D%83%E9%97%AD%E5%90%88%E5%9B%BE/)
173235

Diff for: packages/mcmf/__test__/__snapshots__/codeforce.spec.ts.snap

-17
This file was deleted.

0 commit comments

Comments
 (0)