二分图求最小点集覆盖。题意:贝西驾驶她的飞船在一片N*N的网格状小行星地带。这片网格里面有K个小行星,都位于网格的格点。贝西有一个强大的武器,使用一次可以指定网格地带中任意一行或者一列中的小行星消失,但是这种武器非常昂贵,所以她希望使用尽量少的次数使得这片网格状地带里的小行星全部消失。
我的解题思路:求二分图最小点集覆盖的经典模型。以这片网格状地带的行号和列号分别建立成二分图的两个点集,那么每一个小行星的坐标(x,y)就相当于行号点集中的x与列号点集中的y有一条边,然后求选定最少的行点或者列点使得与所有边都有联系即为求这个二分图的最小点集覆盖。由二分图的最小点集覆盖等于二分图的最大匹配可以得到答案。
我的解题代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define N 555
vector <int> e[N];
int match[N];
bool vis[N];
int n, k;
void InitRead();
void DataProcess();
bool Dfs(int x);
int main()
{
while (~scanf("%d %d", &n, &k))
{
InitRead();
DataProcess();
}
return 0;
}
void InitRead()
{
memset(match, -1, sizeof(match));
for (int i=0; i<=n; ++i)
{
e[i].clear();
}
int a, b;
for (int i=0; i<k; ++i)
{
scanf("%d %d", &a, &b);
e[a].push_back(b);
}
return;
}
void DataProcess()
{
int ans = 0;
for (int i=1; i<=n; ++i)
{
memset(vis, false, sizeof(vis));
if (Dfs(i)) ans++;
}
printf("%d\n", ans);
return;
}
bool Dfs(int x)
{
int size = e[x].size();
for (int i=0; i<size; ++i)
{
if (!vis[e[x][i]])
{
vis[e[x][i]] = true;
if (match[e[x][i]] == -1 || Dfs(match[e[x][i]]))
{
match[e[x][i]] = x;
return true;
}
}
}
return false;
}