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

来源:互联网 发布:淘宝优惠券是什么意思 编辑:程序博客网 时间:2024/05/15 01:23

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

题意:中文题。。。

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

#include <cstdio>#include <cstring>#include <iostream>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;}
0 0
原创粉丝点击