poj 3041 二分图最大匹配
题意:给定一个NxN的网格,其中有k个格点上有障碍物,每次可以消除一行或一列障碍物,问最少几次可以消除全部的障碍物。
思路:二分图的经典模型,将所有的行看作二分图中左边的端点,将所有的列看作右边的端点,当格点上有障碍物时,连一条边,问题转变为求二分图的最小顶点覆盖,根据König定理由二分图的最大匹配得到
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<cstdlib> 7 #include<sstream> 8 #include<iomanip> 9 #include<vector> 10 #include<map> 11 #include<set> 12 #include<queue> 13 using namespace std; 14 const int MOD = 1e9 + 7; 15 16 typedef long long LL; 17 typedef unsigned long long ULL; 18 19 const int maxn = 505; 20 bool g[maxn][maxn]; 21 int link[maxn]; 22 bool check[maxn]; 23 24 int n; 25 26 bool dfs(int u){ 27 for(int i = 1; i <= n; ++i){ 28 if(!check[i] && g[u][i]){ 29 check[i] = true; 30 if(link[i] == -1 || dfs(link[i])){ 31 link[i] = u; 32 return true; 33 } 34 } 35 } 36 return false; 37 } 38 39 int hungarian(){ 40 int ans = 0; 41 memset(link,-1,sizeof(link)); 42 for(int i = 1; i <= n; ++i){ 43 memset(check,0,sizeof(check)); 44 if(dfs(i)) ++ans; 45 } 46 return ans; 47 } 48 49 int main(){ 50 int k; 51 scanf("%d%d",&n,&k); 52 int x,y; 53 for(int i = 0; i < k; ++i){ 54 scanf("%d%d",&x,&y); 55 g[x][y] = 1; 56 } 57 printf("%d\n",hungarian()); 58 return 0; 59 }