HDU - 1281 - 棋盘游戏(二分图匹配)

来源:互联网 发布:优酷网络电视客户端 编辑:程序博客网 时间:2024/06/08 13:20

题目链接:

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

题解:

利用二分图匹配求最大匹配,将棋盘化成一个二分图,横纵坐标分别为左右两团,如果匹配到就说明该点可以放车。然后穷举所有最大匹配找到的边,观察删去该边后最大匹配值是否改变,改变的话即是重要点。

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>using namespace std;int V[505][505];int check[1000];int matching[1000];int matching2[1000];int n,m;bool dfs(int u){    int i;    for(i = 1; i <= m; i++)    {        if(check[i] || V[u][i] != 1)            continue;        check[i] = 1;        if(matching[i] == -1 || dfs(matching[i]))        {            matching[i] = u;            return true;        }    }    return false;}bool dfs2(int u){    int i;    for(i = 1; i <= m; i++)    {        if(check[i] || V[u][i] != 1)            continue;        check[i] = 1;        if(matching2[i] == -1 || dfs(matching2[i]))        {            matching2[i] = u;            return true;        }    }    return false;}int solve(int n_left){    int i, ans = 0;    memset(matching, -1 ,sizeof(matching));    for(i = 1; i <= n_left; i++)    {        memset(check, 0 ,sizeof(check));        if(dfs(i))            ans++;    }    return ans;}int solve2(int n_left){    int i, ans = 0;    memset(matching2, -1 ,sizeof(matching2));    for(i = 1; i <= n_left; i++)    {        memset(check, 0 ,sizeof(check));        if(dfs2(i))            ans++;    }    return ans;}int main(){    int k,cnt = 1 ;    while(cin >> n >> m >> k)    {        int an1, an2 = 0;        memset(V,0,sizeof(V));        while(k--)        {            int a,b;            cin >> a >> b;            V[a][b] = 1;        }        an1 = solve(n);        for(int i = 1; i <= an1; i ++)        {            if(matching[i] > 0)            {                V[matching[i]][i] = 0;                int abc = solve2(n);                V[matching[i]][i] = 1;//删去后一定要再加回去                if(abc < an1)                {                    an2++;                }            }        }        cout << "Board "<< cnt ++<<" have "<< an2<<" important blanks for "<< an1 << " chessmen."<<endl;    }    return 0;}
0 0
原创粉丝点击