题意 :有一个N*N的网格,该网格有K个障碍物.你有一把武器,每次你使用武器可以清楚该网格特定行或列的所有障碍.问你最少需要使用多少次武器能清除网格的所有障碍物?
思路:
将每行、每列分别看作一个点,对于case的每一个行星坐标(x,y),将第x行和第y列连接起来,例如对于输入:
(1,1)、(1,3)、(2,2)、(3,2)4点构造图G:
这样,每个点就相当于图G的一条边,消灭所有点=消灭图G的所有边,又要求代价最少,即找到图G上的最少的点使得这些点覆盖了所有边。
根据定理吗, 最小点覆盖数=最大匹配数,所以本题转化为二分图的最大匹配问题——用匈牙利算法来解决。
#include<iostream>
#include<string>
using namespace std;
#define Max 505
int n, k;
int nx[Max], ny[Max];
int visit[Max];
int x, y, edgeM[Max][Max];
int M_F(int u)
{
for (int i = 1; i <= n; i++)
{
if (edgeM[u][i] && !visit[i])
{
visit[i] = 1;
if (ny[i] == -1 || M_F(ny[i]))
{
nx[u] = i;
ny[i] = u;
return 1;
}
}
}
return 0;
}
int M_make()
{
int u;
int res = 0;
memset(nx, -1, sizeof(nx));
memset(ny, -1, sizeof(ny));
for (int i = 1; i <= n; i++)
{
memset(visit, 0, sizeof(visit));
res += M_F(i);
}
return res;
}
int main()
{
cin >> n >> k;
for (int i = 0; i < k; i++)
{
cin >> x >> y;
edgeM[x][y] = 1;
}
cout<<M_make()<<endl;
return 0;
}