Skip to content

Commit

Permalink
network flow part 3
Browse files Browse the repository at this point in the history
  • Loading branch information
CaveNightingale committed May 6, 2024
1 parent 815755d commit a4c1a90
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 6 deletions.
9 changes: 9 additions & 0 deletions src/lib/component/content/Graph.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
.dark > circle {
fill: gray;
}
.bold > path {
stroke-width: 3;
}
path {
fill: none;
stroke: black;
Expand All @@ -43,6 +46,7 @@
connectedCallback() {
this.recompile();
setTimeout(() => this.recompile(), 500);
new MutationObserver(() => this.recompile()).observe(this, {
childList: true,
subtree: true,
Expand Down Expand Up @@ -115,9 +119,14 @@
for (let v of vertices) {
verticesClasses[v._inner] = v.class ? [v.class] : [];
}
let edgesClasses = {};
for (let e of edges) {
edgesClasses[e._inner.id] = e.class ? [e.class] : [];
}
this.root.innerHTML =
emb.toSvg(this.prevWidth, this.prevHeight, {
graphCss: [],
edgesCss: edgesClasses,
verticesCss: verticesClasses,
displayEdgesWeight: false,
displayEdgesLabel: true,
Expand Down
13 changes: 7 additions & 6 deletions src/lib/component/content/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface Edge {
v: Vertex;
label?: string;
control?: number;
class?: string;
}

function toXY(num: any): [number, number] {
Expand All @@ -31,28 +32,28 @@ function evaluate(str: string, width: number, height: number): [Vertex[], Edge[]
let edges: Edge[] = [];
function vertex(scope: Record<string, any>, pos: any, label: any, className: any) {
let [x, y] = toXY(pos);
let v = { x, y, label: label?.toString(), class: className };
let v = { x, y, label: label?.toString(), class: className?.toString() };
vertices.push(v);
if (scope[label] === undefined) {
scope[label] = v;
scope[label] = v;
}
return v;
}
function edge(scope: Record<string, any>, u: Vertex, v: Vertex, label: any, control: any) {
function edge(scope: Record<string, any>, u: Vertex, v: Vertex, label: any, control: any, className: any) {
if (control !== undefined && typeof control !== "number") {
throw new Error("Control point must be a number");
}
let e = { u, v, label: label?.toString(), control: control };
let e = { u, v, label: label?.toString(), control: control, class: className?.toString() };
edges.push(e);
if (label !== "" && scope[label] === undefined) {
scope[label] = e;
scope[label] = e;
}
return e;
}
let scope: Record<string, any> = { width, height };
scope.vertex = (pos: any, label: any, className: any) => vertex(scope, pos, label, className);
scope.node = scope.vertex;
scope.edge = (u: Vertex, v: Vertex, label: any, control: any) => edge(scope, u, v, label, control);
scope.edge = (u: Vertex, v: Vertex, label: any, control: any, className: any) => edge(scope, u, v, label, control, className);
math.evaluate(str, scope);
return [vertices, edges];
}
Expand Down
99 changes: 99 additions & 0 deletions src/routes/note/network-flow/+page.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,8 +448,107 @@ Combine the previous proof that the number of BFS operations is $O(|V|)$, we hav

</Proof>

<State variant="property">

For any integer-valued capacity function, Dinic's Algorithm gives an integer-valued maximum flow.

</State>

<Proof>

We see that Dinic's Algorithm only uses $+, -, \min$ operations, and the closure property of integers under these operations gives the result.

</Proof>

## Bipartite Matching

Bipartite matching problem is a special case of network flow problem. Let describe the problem formally first.

<State variant="definition">

Given a bipartite graph $G = (U, V, E)$, where $U$ and $V$ are two disjoint sets of vertices and $E$ is the set of edges connecting vertices in $U$ and $V$. The **bipartite matching** is a subset of edges $M \subseteq E$ such that no two edges in $M$ share a common vertex.

</State>

<State variant="example">

<Graph>

```
node(100 + 75i, "u_1");
node(200 + 75i, "u_2");
node(300 + 75i, "u_3");
node(400 + 75i, "u_4");
node(50 + 225i, "v_1");
node(150 + 225i, "v_2");
node(250 + 225i, "v_3");
node(350 + 225i, "v_4");
node(450 + 225i, "v_5");
edge(u_1, v_1);
edge(u_1, v_2, "", 0, "bold");
edge(u_2, v_2);
edge(u_2, v_4, "", 0, "bold");
edge(u_3, v_3);
edge(u_3, v_1, "", 0, "bold");
edge(u_3, v_5);
edge(u_4, v_2);
edge(u_4, v_3, "", 0, "bold");
edge(u_4, v_5);
```

</Graph>

To make things clear, we draw the source $s$ and sink $t$ explicitly. All edges have capacity $1$ and is from top to bottom. Bold edges are the edges in the bipartite matching, or in another word, the edges with flow $1$. And for any integer-valued flow, there is a corresponding bipartite matching $M = \{(u, v) \in E| f(u, v) = 1\}$.

<Graph>

<!--
Notice that dictionary order is required for edge (u, v) in jsGraph library.
Actually I hate this.
-->
```
node(250 + 25i, "s");
node(100 + 75i, "u_1");
node(200 + 75i, "u_2");
node(300 + 75i, "u_3");
node(400 + 75i, "u_4");
node(50 + 225i, "v_1");
node(150 + 225i, "v_2");
node(250 + 225i, "v_3");
node(350 + 225i, "v_4");
node(450 + 225i, "v_5");
node(250 + 275i, "t");
edge(s, u_1, "", 0, "bold");
edge(s, u_2, "", 0, "bold");
edge(s, u_3, "", 0, "bold");
edge(s, u_4, "", 0, "bold");
edge(u_1, v_1);
edge(u_1, v_2, "", 0, "bold");
edge(u_2, v_2);
edge(u_2, v_4, "", 0, "bold");
edge(u_3, v_3);
edge(u_3, v_1, "", 0, "bold");
edge(u_3, v_5);
edge(u_4, v_2);
edge(u_4, v_3, "", 0, "bold");
edge(u_4, v_5);
edge(t, v_1, "", 0, "bold");
edge(t, v_2, "", 0, "bold");
edge(t, v_3, "", 0, "bold");
edge(t, v_4, "", 0, "bold");
edge(t, v_5);
```

</Graph>

</State>

<State variant="theorem">

Dinic's Algorithm can terminate in $O(\sqrt{|V|}|E|)$ time for bipartite matching problem.

</State>

To be continued.

## Min-Cost Flow
Expand Down

0 comments on commit a4c1a90

Please sign in to comment.