0%

Hungarian Algorithm

https://www.renfei.org/blog/bipartite-matching.html https://en.wikipedia.org/wiki/Matching_(graph_theory)

Hungarian Algorithm

Given a matching M,

  • an alternating path is a path that begins with an unmatched vertex and whose edges belong alternately to the matching and not to the matching.
  • an augmenting path is an alternating path that starts from and ends on free (unmatched) vertices.

Traverse all the points on the left, for each point \(u\) if we can find a augmenting path \(\vec{p}\) starting from \(u\), then we use the edges of \(\vec{p}\) to update the matches of each point on \(\vec{p}\).

Problems

HDU 1068 Girls and Boys

This problem is to figure out the number of maximum independent set of bipartite graph.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <bits/stdc++.h>
#define DBG(x) cerr << #x << " = " << x << endl

using namespace std;
typedef long long LL;

const int MAXN = 1024;

vector<int> g[MAXN];
int match[MAXN];
bool vis[MAXN];

void init(int n) {
for (int i = 0; i < n; i++) {
g[i].clear();
}
fill(match, match + n, -1);
}

bool dfs(int u) {
for (auto v : g[u]) {
if (vis[v]) continue;
vis[v] = true;
if (match[v] == -1 || dfs(match[v])) {
match[v] = u;
return true;
}
}

return false;
}

int hungary(int n) {
int ans = 0;
for (int i = 0; i < n; i++) {
fill(vis, vis + n, false);
if (dfs(i)) ans++;
}
return ans / 2;
}

int main(int argc, char **argv) {
int n;
while (scanf("%d", &n) != EOF) {
init(n);
for (int i = 0; i < n; i++) {
int u, cnt;
scanf("%d: (%d) ", &u, &cnt);
for (int j = 0; j < cnt; j++) {
int v;
scanf("%d", &v);
g[u].push_back(v);
}
}
printf("%d\n", n - hungary(n));
}
return 0;
}

HDU 1179 Ollivanders: Makers of Fine Wands since 382 BC.

There are 3 ways to solve the problem.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <bits/stdc++.h>
#define DBG(x) cerr << #x << " = " << x << endl

using namespace std;
typedef long long LL;

const int MAXN = 128;
vector<int> g[MAXN];
int match[MAXN];
bool vis[MAXN];

void init(int n, int m) {
for (int i = 1; i <= m; i++) {
g[i].clear();
}
fill(match + 1, match + 1 + n, -1);
}

void add(int u, int v) {
g[u].push_back(v);
}

bool dfs(int u) {
for (auto v : g[u]) {
if (vis[v]) continue;
vis[v] = true;
if (match[v] == -1 || dfs(match[v])) {
match[v] = u;
return true;
}
}
return false;
}

int hungary(int n, int m) {
int ans = 0;
for (int i = 1; i <= m; i++) {
fill(vis + 1, vis + 1 + n, false);
if (dfs(i)) ans++;
}
return ans;
}

int main(int argc, char **argv) {
int n, m;
while (scanf("%d%d", &n, &m) != EOF) {
init(n, m);
for (int i = 1; i <= m; i++) {
int c;
scanf("%d", &c);
for (int j = 0; j < c; j++) {
int v;
scanf("%d", &v);
add(i, v);
}
}
printf("%d\n", hungary(n, m));
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <bits/stdc++.h>
#define DBG(x) cerr << #x << " = " << x << endl

using namespace std;
typedef long long LL;

const int MAXN = 128 * 2;

vector<int> g[MAXN];
int match[MAXN];
bool vis[MAXN];

void add(int u, int v) {
g[u].push_back(v);
}

void init(int n, int m) {
for (int i = 1; i <= n + m; i++) {
g[i].clear();
}
fill(match + 1, match + 1 + n, -1);
}

bool dfs(int u) {
for (auto v : g[u]) {
if (vis[v]) continue;
vis[v] = true;
if (match[v] == -1 || dfs(match[v])) {
match[v] = u;
return true;
}
}
return false;
}

int hungarian(int n, int m) {
int ans = 0;
for (int u = n + 1; u <= n + m; u++) {
fill(vis + 1, vis + 1 + n, false);
if (dfs(u)) ans++;
}
return ans;
}

int main(int argc, char **argv) {
int n, m;
while (scanf("%d%d", &n, &m) != EOF) {
init(n, m);
for (int u = n + 1; u <= n + m; u++) {
int c;
scanf("%d", &c);
for (int j = 0; j < c; j++) {
int v;
scanf("%d", &v);
add(u, v);
add(v, u);
}
}
printf("%d\n", hungarian(n, m));
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <bits/stdc++.h>
#define DBG(x) cerr << #x << " = " << x << endl

using namespace std;
typedef long long LL;

const int MAXN = 128 * 2;

vector<int> g[MAXN];
int match[MAXN];
bool vis[MAXN];

void init(int n, int m) {
for (int i = 1; i <= n + m; i++) {
g[i].clear();
}
fill(match + 1, match + 1 + n + m, -1);
}

bool dfs(int u) {
for (auto v : g[u]) {
if (vis[v]) continue;
vis[v] = true;
if (match[v] == -1 || dfs(match[v])) {
match[v] = u;
return true;
}
}
return false;
}

int hungarian(int n, int m) {
int ans = 0;
for (int u = 1; u <= n + m; u++) {
fill(vis + 1, vis + 1 + n + m, false);
if (dfs(u)) ans++;
}
return ans / 2;
}

void add(int u, int v) {
g[u].push_back(v);
}

int main(int argc, char **argv) {
int n, m;
while (scanf("%d%d", &n, &m) != EOF) {
init(n, m);
for (int u = n + 1; u <= n + m; u++) {
int c;
scanf("%d", &c);
for (int j = 0; j < c; j++) {
int v;
scanf("%d", &v);
add(u, v);
add(v, u);
}
}
printf("%d\n", hungarian(n, m));
}
return 0;
}