二分匹配-hdu-1281

这道题如果读懂了,就很简单。

大致题意:

一个n*m的棋盘,有k个可以放‘車’的格子,放完‘車’之后,要保证不能互相攻击。

假设最多能放t个‘車’。

如果某个能放‘車’的格子现在不可以放了,且结果最多能放的‘車’数目不是t了,就称这个格子为重要点。

最后输出重要点的数目和t。

大致思路:

先将最大数目求出来,也就是利用行和列(将可放的格子的行和列进行连边)两个集合求出最大匹配ans。

然后在一一枚举每个格子不可以放的时候,再求出最大匹配数,看看是否为ans,不是的话,则为重要点。

代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int ma[200][200];
int x[200];
int y[200];
int lx[200];
int rx[200];
int vis[200];
int n,m,k;
int dfs(int k)
{
    for(int i=1; i<=m; i++)
    {
        if(ma[k][i]&&!vis[i])
        {
            vis[i]=1;
            if(rx[i]==-1||dfs(rx[i]))
            {
                lx[k]=i;
                rx[i]=k;
                return true;
            }
        }
    }
    return false;
}
int main()
{
    int fas=0;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        memset(ma,0,sizeof(ma));
        memset(lx,-1,sizeof(lx));
        memset(rx,-1,sizeof(rx));
        int ans=0;
        int r,c;
        for(int i=1; i<=k; i++)
        {
            scanf("%d%d",&r,&c);
            x[i]=r;
            y[i]=c;
            ma[r][c]=1;
        }
        for(int i=1; i<=n; i++)
        {
            memset(vis,0,sizeof(vis));
            if(lx[i]==-1&&dfs(i))
            {
                ans++;
            }
        }

        int kas;
        int cas=0;
        for(int i=1; i<=k; i++)
        {
            ma[x[i]][y[i]]=0;//这个格子不可以放了
            memset(lx,-1,sizeof(lx));
            memset(rx,-1,sizeof(rx));
            kas=0;
            for(int i=1; i<=n; i++)
            {
                memset(vis,0,sizeof(vis));
                if(lx[i]==-1&&dfs(i))
                {
                    kas++;
                }
            }
            //cout<<"++"<<x[i]<<" "<<y[i]<<" "<<kas<<endl;
            if(kas!=ans)
            {
                cas++;
            }
             ma[x[i]][y[i]]=1;//回溯
        }
        printf("Board %d have %d important blanks for %d chessmen.\n",++fas,cas,ans);
    }
}

猜你喜欢

转载自blog.csdn.net/zyy_1998/article/details/79298032