[POJ3041]Asteroids(二分图,最大匹配)

题目链接:http://poj.org/problem?id=3041

题意:N*N中选最少行或者列,可以覆盖所有的点。

最小点覆盖问题,等于最大匹配。

建图:考虑行,选中某一行,那么行上的点对应的列则不需要被选。根据这一条,建图就行。

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <iomanip>
 4 #include <cstring>
 5 #include <climits>
 6 #include <complex>
 7 #include <cassert>
 8 #include <cstdio>
 9 #include <bitset>
10 #include <vector>
11 #include <deque>
12 #include <queue>
13 #include <stack>
14 #include <ctime>
15 #include <set>
16 #include <map>
17 #include <cmath>
18 using namespace std;
19 
20 typedef pair<int, int> pii;
21 const int maxn = 1050;
22 const int inf = 0x3f3f3f3f;
23 int n, k;
24 int G[maxn][maxn];
25 int nx,ny;
26 int linker[maxn],lx[maxn],ly[maxn];
27 int slack[maxn];
28 bool visx[maxn],visy[maxn];
29 
30 bool dfs(int x) {
31     visx[x] = true;
32     for(int y = 0; y < ny; y++) {
33         if(visy[y])continue;
34         int tmp = lx[x] + ly[y] - G[x][y];
35         if(tmp == 0) {
36             visy[y] = true;
37             if(linker[y] == -1 || dfs(linker[y])) {
38                 linker[y] = x;
39                 return true;
40             }
41         }
42         else if(slack[y] > tmp)
43             slack[y] = tmp;
44     }
45     return false;
46 }
47 
48 int km() {
49     memset(linker,-1,sizeof(linker));
50     memset(ly,0,sizeof(ly));
51     for(int i = 0;i < nx;i++) {
52         lx[i] = -inf;
53         for(int j = 0;j < ny;j++)
54             if(G[i][j] > lx[i])
55                 lx[i] = G[i][j];
56     }
57     for(int x = 0;x < nx;x++) {
58         for(int i = 0;i < ny;i++)
59             slack[i] = inf;
60         while(true) {
61             memset(visx,false,sizeof(visx));
62             memset(visy,false,sizeof(visy));
63             if(dfs(x))break;
64             int d = inf;
65             for(int i = 0;i < ny;i++)
66                 if(!visy[i] && d > slack[i])
67                     d = slack[i];
68             for(int i = 0;i < nx;i++)
69                 if(visx[i])
70                     lx[i] -= d;
71             for(int i = 0;i < ny;i++) {
72                 if(visy[i])ly[i] += d;
73                 else slack[i] -= d;
74             }
75         }
76     }
77     int res = 0;
78     for(int i = 0;i < ny;i++)
79         if(linker[i] != -1)
80             res += G[linker[i]][i];
81     return res;
82 }
83 
84 int main() {
85     // freopen("in", "r", stdin);
86     int x, y;
87     while(~scanf("%d%d",&n,&k)) {
88         memset(G, 0, sizeof(G));
89         for(int i = 1; i <= k; i++) {
90             scanf("%d%d",&x,&y);
91             G[x-1][y-1]++;
92         }
93         nx = n, ny = n;
94         printf("%d
", km());
95     }
96     return 0;
97 }
原文地址:https://www.cnblogs.com/kirai/p/6774001.html