From a4c1a90764fd7e09be579832e655cd1b7ca177f9 Mon Sep 17 00:00:00 2001 From: CaveNightingale Date: Mon, 6 May 2024 14:50:42 +0800 Subject: [PATCH] network flow part 3 --- src/lib/component/content/Graph.svelte | 9 +++ src/lib/component/content/graph.ts | 13 ++-- src/routes/note/network-flow/+page.md | 99 ++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 6 deletions(-) diff --git a/src/lib/component/content/Graph.svelte b/src/lib/component/content/Graph.svelte index 310227a..b3b0248 100644 --- a/src/lib/component/content/Graph.svelte +++ b/src/lib/component/content/Graph.svelte @@ -21,6 +21,9 @@ .dark > circle { fill: gray; } + .bold > path { + stroke-width: 3; + } path { fill: none; stroke: black; @@ -43,6 +46,7 @@ connectedCallback() { this.recompile(); + setTimeout(() => this.recompile(), 500); new MutationObserver(() => this.recompile()).observe(this, { childList: true, subtree: true, @@ -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, diff --git a/src/lib/component/content/graph.ts b/src/lib/component/content/graph.ts index d7e373c..301ec00 100644 --- a/src/lib/component/content/graph.ts +++ b/src/lib/component/content/graph.ts @@ -12,6 +12,7 @@ interface Edge { v: Vertex; label?: string; control?: number; + class?: string; } function toXY(num: any): [number, number] { @@ -31,28 +32,28 @@ function evaluate(str: string, width: number, height: number): [Vertex[], Edge[] let edges: Edge[] = []; function vertex(scope: Record, 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, u: Vertex, v: Vertex, label: any, control: any) { + function edge(scope: Record, 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 = { 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]; } diff --git a/src/routes/note/network-flow/+page.md b/src/routes/note/network-flow/+page.md index d62858f..7c26445 100644 --- a/src/routes/note/network-flow/+page.md +++ b/src/routes/note/network-flow/+page.md @@ -448,8 +448,107 @@ Combine the previous proof that the number of BFS operations is $O(|V|)$, we hav + + +For any integer-valued capacity function, Dinic's Algorithm gives an integer-valued maximum flow. + + + + + +We see that Dinic's Algorithm only uses $+, -, \min$ operations, and the closure property of integers under these operations gives the result. + + + ## Bipartite Matching +Bipartite matching problem is a special case of network flow problem. Let describe the problem formally first. + + + +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. + + + + + + + +``` +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); +``` + + + +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\}$. + + + + +``` +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); +``` + + + + + + + +Dinic's Algorithm can terminate in $O(\sqrt{|V|}|E|)$ time for bipartite matching problem. + + + To be continued. ## Min-Cost Flow