HDU OJ 1281 棋盘游戏【二分图匹配之最大匹配重要点】

原题连接:点击打开链接

题意:…………

思路:求最多能放多少个 “车”,可以转化成 二分图的最大匹配!,把能放的点的 横纵座标 当作 二分图的一条边!最大匹配就满足了题目中任意两个“车”不会互相吃到的条件,因为匹配结果,会使得棋盘中的匹配点(也就是二分图中的匹配边),不在同一列且不再同一行。求出最大匹配后 ,则重要点必定在最大匹配的边上!依次去掉每条便,再求最大匹配看和原匹配是否相等即可!

代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
vector<int>V[1000];
int link[1000],use[1000];
void init(int n)
{
    int i;
    for(i=0;i<=n;i++)
      V[i].clear();
}
bool Dfs(int v)
{
    int i,j,k;
    for(i=0;i<V[v].size();i++)
    {
        k=V[v][i];
        if(!use[k])
        {
            use[k]=1;
            if(!link[k]||Dfs(link[k]))
            {
                link[k]=v;
                return true;
            }
        }
    }
    return false;
}
int MaxMatch(int n)
{
    int i,j,ans=0;
    memset(link,0,sizeof(link));
    for(i=1;i<=n;i++)
    {
        memset(use,0,sizeof(use));
        if(Dfs(i))
            ans++;
    }
    return ans;

}
int main()
{
    int i,j,n,m,k,t=0;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        t++;
        init(n);
        int x,y;
        while(k--)
        {
            scanf("%d%d",&x,&y);
            V[x].push_back(y);
        }
        int ans=MaxMatch(n);
        int imp=0;
        for(i=1;i<=n;i++)
        {
            for(j=0;j<V[i].size();j++)
            {
                k=V[i][j];
                V[i].erase(V[i].begin()+j);
               // printf("去掉边  %d----%d\n",i,k);
                int cnt=MaxMatch(n);
                if(cnt<ans)
                       imp++;
                V[i].insert(V[i].begin()+j,k);
            }
        }
        printf("Board %d have %d important blanks for %d chessmen.\n",t,imp,ans);
    }
}
点赞