hdu2819棋盘游戏(二分图匹配)

看完这道题,没什么思路,只知道求如何求第二问。看了别人题解突然恍然大悟。由于不能放车的地方不影响车的互相攻击,所以就相当于是列去匹配行,题目中给出的点(x,y),转化为g[x}[y}=1(只需要x->y即可),其他位置都是0。而求第一问,就是枚举每一个点,把它去掉之后再算一遍最大匹配,如果算出来 < ans2,说明它是关键点。这种思路和次小生成树的求法是一样的,
连暴力枚举都不会的渣渣=。=|||

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <stack>
#include <vector>
#include <string.h>
#include <queue>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
const int MAXN=105;
int n,m;
bool g[MAXN][MAXN];
int x[MAXN*MAXN],y[MAXN*MAXN];
int linker[MAXN];
bool used[MAXN];
bool dfs(int u)
{
    for(int v=0;v<m;v++)
        if(g[u][v]&&!used[v]){
            used[v]=true;
            if(linker[v]==-1||dfs(linker[v])){
                linker[v]=u;
                return true;
            }
        }
    return false;
}
int hungary(void)
{
    int res=0;
    msc(linker);
    for(int u=0;u<n;u++)
    {
        ms(used);
        if(dfs(u)) res++;
    }
    return res;
}
int main(int argc, char const *argv[])
{   
    int k,ti=0;
    while(scanf("%d %d %d",&n,&m,&k)==3)
    {
        ms(g);
        for(int i=0;i<k;i++)
        {
            scanf("%d %d",x+i,y+i);
            x[i]--;
            y[i]--;
            g[x[i]][y[i]]=true;
        }
        int ans1=0,ans2=hungary();
        for(int i=0;i<k;i++)
        {
            g[x[i]][y[i]]=false;
            if(hungary()<ans2) ans1++;
            g[x[i]][y[i]]=true;
        }
printf("Board %d have %d important blanks for %d chessmen.\n",
    ++ti,ans1,ans2);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值