1function bipartiteMatch(n, edges) {
2 const adj = Array.from({ length: n }, () => []);
3 for (const [u, v] of edges) { adj[u].push(v); adj[v].push(u); }
4 const color = new Array(n).fill(0); // 0未染色 1/2两色
5 for (let s = 0; s < n; s++) {
6 if (color[s]) continue;
7 color[s] = 1;
8 const q = [s];
9 while (q.length) {
10 const u = q.shift();
11 for (const v of adj[u]) {
12 if (!color[v]) { color[v] = 3 - color[u]; q.push(v); }
13 else if (color[v] === color[u]) return false; // 不是二分图
14 }
15 }
16 }
17 // 匈牙利算法求最大匹配(左集 = 颜色1)
18 const matchR = new Array(n).fill(-1);
19 const dfs = (u, seen) => {
20 for (const v of adj[u]) {
21 if (seen[v]) continue;
22 seen[v] = true;
23 if (matchR[v] === -1 || dfs(matchR[v], seen)) { matchR[v] = u; return true; }
24 }
25 return false;
26 };
27 let matching = 0;
28 for (let u = 0; u < n; u++) {
29 if (color[u] !== 1) continue;
30 if (dfs(u, new Array(n).fill(false))) matching++;
31 }
32 return matching;
33}