题意:给定二分图求最大匹配数和关键匹配数。
思路:先通过匈牙利算法求最大匹配数,然后遍历二分图,去掉一条边之后再用匈牙利算法算匹配数,如果小于最大匹配数,则这个边为关键点。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
int m,n,k;
int path[110][110];
bool used[110];
int match[110];
bool Dfs(int x)
{
for (int i = 1; i <= m; i++)
{
if (!used[i] && path[x][i])
{
used[i] = true;
if (!match[i] || Dfs(match[i]))
{
match[i] = x;
return true;
}
}
}
return false;
}
int Matching()
{
int ans = 0;
memset(match, 0, sizeof(match));
for (int i = 1; i <= n; i++)
{
memset(used, false, sizeof(used));
if (Dfs(i))
{
ans++;
}
}
return ans;
}
int main(void)
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t = 1;
while (~scanf("%d %d %d", &n, &m, &k))
{
memset(path,0,sizeof(path));
for (int i = 0; i < k; i++)
{
int x, y;
scanf("%d %d", &x, &y);
path[x][y] = 1;
}
int ans = Matching();
int count = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (path[i][j])
{
path[i][j]=false;
int tmp = Matching();
path[i][j] = true;
if (tmp < ans)
count++;
}
}
}
printf("Board %d have %d important blanks for %d chessmen.\n", t++, count, ans);
}
return 0;
}