HDU-1281 棋盘游戏

来源:互联网 发布:js插件编写 编辑:程序博客网 时间:2024/05/29 17:45

这是二分图匹配中的棋盘问题


这类题的也很经典。


但是这类题目看着和二分匹配好像完全搭不上边


如何把这类题目转化为二分图匹配了


究竟是用什么去匹配什么,或者说把什么分为两堆,然后去找一一对应


在大多数的题解中都没有提到这个问题,但是我觉得二分图匹配问题的核心就是这了


究竟如何把问题转化为二分图匹配问题


那么对于这道题


方法是用行匹配列或者用列匹配行


简单来讲就是


对于每一行,我只选一个位置,然后选第二行的时候我再选一个位置,一直到每一行都选一个位置为止


这样保证每行只有一个,此处match[i]表示第 i 列的棋子再第几行


这样就是用列去匹配行


#include<bits/stdc++.h>using namespace std;const int maxn=110;int match[maxn];int vis[maxn];int e[maxn][maxn];int n,m,k;struct node{    int x,y;}zb[maxn*maxn];bool find(int u){    for(int i=1;i<=m;i++)    {        if(!vis[i]&&e[u][i])        {            vis[i]=1;            if(!match[i]||find(match[i]))            {                match[i]=u;                return true;            }        }    }    return false;}int main(){    int step=0;    while(scanf("%d%d%d",&n,&m,&k)!=EOF)    {        int ans=0,cnt=0,inf=0;        memset(e,0,sizeof(e));        memset(match,0,sizeof(match));        for(int i=0;i<k;i++)        {            scanf("%d%d",&zb[i].x,&zb[i].y);            e[zb[i].x][zb[i].y]=1;        }        for(int i=1;i<=n;i++)        {            memset(vis,0,sizeof(vis));            if(find(i))                ans++;        }        for(int i=0;i<k;i++)        {            e[zb[i].x][zb[i].y]=0;            cnt=0;            memset(match,0,sizeof(match));            for(int j=1;j<=n;j++)            {                memset(vis,0,sizeof(vis));                if(find(j))                    cnt++;            }            if(cnt!=ans)            {                inf++;            }            e[zb[i].x][zb[i].y]=1;        }        printf("Board %d have %d important blanks for %d chessmen.\n",++step,inf,ans);    }    return 0;}




原创粉丝点击