hdu 1281 棋盘游戏

来源:互联网 发布:pc护眼软件 编辑:程序博客网 时间:2024/05/29 05:07

http://acm.hdu.edu.cn/showproblem.php?pid=1281

把横纵坐标建成二分图,求最大匹配

本题要求关键点,那么只需要对于每个可行点进行删点,然后看看得出的最大匹配是否小于不删点的解,如果小于,则是关键点……统计一下即可。


Sample Input
3 3 41 21 32 12 23 3 41 21 32 13 2
 

Sample Output
Board 1 have 0 important blanks for 2 chessmen.Board 2 have 3 important blanks for 3 chessmen.

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <cmath>#include <cstdlib>#include <limits>#include <queue>#include <stack>#include <vector>#include <map>using namespace std;#define N 1350#define INF 0xfffffff#define PI acos (-1.0)#define EPS 1e-8int n, m, k, used[N], vis[N], g[N][N];int DFS (int u);///匈牙利二分匹配int solve ();///求最大匹配int main (){    int flag = 1;    while (~scanf ("%d %d %d", &n, &m, &k))    {        memset (g, 0, sizeof (g));        memset (used, 0, sizeof (used));        for (int i=0; i<k; i++)        {            int a, b;            scanf ("%d %d", &a, &b);            g[a][b] = 1;        }        int ans = solve ();///最大匹配数        int cnt = 0;        for (int i=1; i<=n; i++)            for (int j=1; j<=m; j++)                if (g[i][j])                {                    memset (used, 0, sizeof (used));///再次初始化                    g[i][j] = 0;                    if (solve () < ans) cnt++;///判断去掉这个点后能不能达到最大匹配                    g[i][j] = 1;///不要忘记还将g[i][j]置为1                }        printf ("Board %d have %d important blanks for %d chessmen.\n", flag++, cnt, ans);    }    return 0;}int DFS (int u){    for (int i=1; i<=m; i++)    {        if (!vis[i] && g[u][i])        {            vis[i] = true;            if (!used[i] || DFS (used[i]))            {                used[i] = u;                return true;            }        }    }    return false;}int solve (){    int ans = 0;    for (int i=1; i<=n; i++)    {        memset (vis, false, sizeof (vis));        if (DFS (i)) ans++;    }    return ans;}


1 0