二分图最大匹配

匈牙利算法,通过反复寻找增广路的方法求最大匹配。

 1 const int MAXV = 1001;
 2 int V;                //顶点数
 3 vector<int> G[MAXV];  //图的邻接表表示
 4 int match[MAXV];      //所匹配的定点
 5 bool used[MAXV];      // DFS中用到的访问标记
 6 
 7 //添加无向边,注意顶点编号从0开始
 8 void add_edge(int u, int v) {
 9     G[u].push_back(v);
10     G[v].push_back(u);
11 }
12 
13 //通过DFS寻找增广路
14 bool dfs(int v) {
15     used[v] = true;
16     for (int i = 0; i < G[v].size(); i++) {
17         int u = G[v][i], w = match[u];
18         if (w < 0 || !used[w] && dfs(w)) {
19             match[v] = u;
20             match[u] = v;
21             return true;
22         }
23     }
24     return false;
25 }
26 
27 //二分图最大匹配,返回最大匹配数
28 int Bipartite_Matching() {
29     int res = 0;
30     memset(match, -1, sizeof(match));
31     for (int v = 0; v < V; v++) {
32         if (match[v] < 0) {
33             memset(used, 0, sizeof(used));
34             if (dfs(v)) {
35                 res++;
36             }
37         }
38     }
39     return res;
40 }

POJ3041

题意:

 在一个N*N的网格上有K个小行星,小行星的位置是($R_i$, $C_i$),有武器一次可以摧毁或一列的小行星,问最少几次使用武器可以将小行星全部摧毁。

解法:

把光束(横、纵两种)当作顶点,把小行星的位置当作边。问题就是选若干个点(光束)覆盖所有的边,这是最小顶点覆盖(任意边都有只少一个顶点被涵盖),等效于最大匹配。

横纵两种光束是二分图,所以直接二分最大匹配即可。

代码如下:

 1 const int MAXV = 1001;
 2 int V;                //顶点数
 3 vector<int> G[MAXV];  //图的邻接表表示
 4 int match[MAXV];      //所匹配的定点
 5 bool used[MAXV];      // DFS中用到的访问标记
 6 
 7 //添加无向边,注意顶点编号从0开始
 8 void add_edge(int u, int v) {
 9     G[u].push_back(v);
10     G[v].push_back(u);
11 }
12 
13 //通过DFS寻找增广路
14 bool dfs(int v) {
15     used[v] = true;
16     for (int i = 0; i < G[v].size(); i++) {
17         int u = G[v][i], w = match[u];
18         if (w < 0 || !used[w] && dfs(w)) {
19             match[v] = u;
20             match[u] = v;
21             return true;
22         }
23     }
24     return false;
25 }
26 
27 //二分图最大匹配,返回最大匹配数
28 int Bipartite_Matching() {
29     int res = 0;
30     memset(match, -1, sizeof(match));
31     for (int v = 0; v < V; v++) {
32         if (match[v] < 0) {
33             memset(used, 0, sizeof(used));
34             if (dfs(v)) {
35                 res++;
36             }
37         }
38     }
39     return res;
40 }
41 
42 const int MAXK = 10000 + 5;
43 int N, K;
44 int R[MAXK], C[MAXK];
45 
46 int main() {
47 #ifndef ONLINE_JUDGE
48     freopen("input.txt", "r", stdin);
49 #endif  // !ONLINE_JUDGE
50     N = READ(), K = READ();
51     REP(i, 1, K) {
52         int R = READ(), C = READ();
53         add_edge(R - 1, C + N - 1);
54     }
55     V = N + N;
56     printf("%d
", Bipartite_Matching());
57     return 0;
58 }
原文地址:https://www.cnblogs.com/romaLzhih/p/9489795.html