题意:在一个网格中有若干个点,每一次可以清除一行或者一列,问最少几次可以将网格中的点全部清除。
思路:这个题是一个入门的最大匹配题(这个好像不是思路..)。一般的方式就是将 行 看作集合A,列 看作集合B。
这么说有点抽象。举个例子:2行3列的矩阵可以看作是集合A={1,2}与B={1,2,3},假设矩阵[1][2] 存在点(别忘了题意),则A中的元素1与B中元素2连有一条边。
这样就可以将题给矩阵转化为二分图,再利用匈牙利算法得到最大匹配数就是答案了。
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 int n, k; 5 int v1, v2;//二分图顶点集,都等于n 6 bool map[501][501]; 7 bool visit[501]; //记录v2中的每个点是否被搜索过 8 int link[501]; //记录v2中的点y在v1中所匹配的点x的编号 9 int result;//最大匹配数 10 bool dfs(int x) 11 12 { 13 for (int y = 1; y <= v2; y++) 14 { 15 if (map[x][y] && !visit[y]) 16 { 17 visit[y] = true; 18 if (link[y] == 0 || dfs(link[y])) 19 { 20 link[y] = x; 21 return 1; 22 } 23 } 24 } 25 return 0; 26 } 27 28 //匈牙利算法hungary algorithm 29 void search() 30 { 31 for (int x = 1; x <= v1; x++) 32 { 33 34 memset(visit,false,sizeof(visit)); 35 36 if (dfs(x)) //从v1中的节点x开始寻找增广路径p 37 38 result++; 39 } 40 } 41 42 int main() 43 { 44 cin >> n >> k; 45 v1 = v2 = n; 46 int x, y; 47 memset(map,0,sizeof(map)); 48 for (int i = 1; i <= k; i++) 49 { 50 cin >> x >> y; 51 map[x][y] = true; 52 } 53 search(); 54 cout << result << endl; 55 return 0; 56 }
原文地址:https://www.cnblogs.com/llllrj/p/9398378.html
时间: 2024-10-12 20:13:37