hdu1281(二分图匹配)

来源:互联网 发布:android编程教程 编辑:程序博客网 时间:2024/05/22 23:52
//把行和列变成点,能放的点就把行和列连起来  
//求二分图最大匹配就是最多能放的棋子数,这  
//还是比较基础的,但是在于怎么求相同的点的  
//个数,因为每一条边相当于一个点,我们可以  
//枚举删除每一条边,看二分图匹配的值是否会变 
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,m;int bmap[105][105];int p[105][105];int x[105*105],y[105*105];int match[105];int vis[105];bool dfs(int u){    vis[u] = 1;    for(int i=1;i<=m;i++)    {        if(bmap[u][i]&&!p[u][i])        {            if(match[i]==-1||!vis[match[i]]&&dfs(match[i]))            {                match[i] = u;                return true;            }        }    }    return false;}int main(){    int k,a,b,t = 1;    while(scanf("%d%d%d",&n,&m,&k)!=EOF)    {        memset(bmap,0,sizeof(bmap));        memset(p,0,sizeof(p));        for(int i=0;i<k;i++)        {            scanf("%d%d",&x[i],&y[i]);            bmap[x[i]][y[i]] = 1;        }        memset(match,-1,sizeof(match));        int ans = 0;        for(int i=1;i<=n;i++)        {            memset(vis,0,sizeof(vis));            if(dfs(i)) ans++;        }        int sum = 0;        for(int i=0;i<k;i++)        {            int res = 0;            memset(match,-1,sizeof(match));            p[x[i]][y[i]] = 1;            for(int i=1;i<=n;i++) {memset(vis,0,sizeof(vis)); if(dfs(i)) res++;}            if(res!=ans) sum ++;            p[x[i]][y[i]] = 0;        }        printf("Board %d have %d important blanks for %d chessmen.\n",t++,sum,ans);    }    return 0;}