[HDU 1281] 棋盘游戏 最大匹配

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

题意:中文题。。。

思路:话说这题看了好久不会写啊,最后看题解说是个最大匹配,图论太太太弱了。。。
由于每一行每一列只能放一个棋子,所以可以讲放棋子的过程看作是一个匹配,用行匹配列,匹配边就是放棋子的位置,先求出一个最大匹配,然后枚举最大匹配中的点,将每个边尝试消除看能否得到最大匹配。

#include 
#include 
#include 

using namespace std;

struct Point{
    int x, y;
    Point(int a = 0, int b = 0){
        x = a, y = b;
    }
};

int n, m, s;
int link[105];
bool vis[105];
bool mapn[105][105];

Point res[105];

bool hungary(int rt)  //匈牙利
{
    for(int i = 1; i <= m; i++){
        if(mapn[rt][i] && !vis[i]){
            vis[i] = true;
            if(link[i] == -1 || hungary(link[i])){
                link[i] = rt;
                return true;
            }
        }
    }
    return false;
}


int main()
{
    int tt = 1;
    while(~scanf("%d%d%d", &n, &m, &s)){
        int x, y;
        memset(link, -1, sizeof(link));
        memset(mapn, false, sizeof(mapn));
        for(int i = 0; i < s; i++){
            scanf("%d%d", &x, &y);
            mapn[x][y] = true;
        }
        for(int i = 1; i <=n; i++){  //求最大匹配
            memset(vis, false, sizeof(vis));
            hungary(i);
        }
        int top = 0;
        for(int i = 1; i <= m; i++){
            if(link[i] != -1){
                res[top++] = Point(link[i], i);  //取出最大匹配的边
            }
        }
        int resl = 0;
        for(int i = 0; i < top; i++){
            mapn[res[i].x][res[i].y] = false; //尝试删除最大匹配中的边
            int sum = 0;
            memset(link, -1, sizeof(link));
            for(int k = 1; k <= n; k++){
                memset(vis, false, sizeof(vis));
                sum += hungary(k);
            }
            resl += (sum != top);
            mapn[res[i].x][res[i].y] = true;
        }
        printf("Board %d have %d important blanks for %d chessmen.\n", tt++, resl, top);
    }
    return 0;
}

你可能感兴趣的:(图论)