本文主要是介绍hdu1281(匈牙利算法),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
链接:点击打开链接
题意:给出一个N*M的棋盘,现在给出K个位置可以放棋子,现要求每行每列最多放一个棋子,求最多放的棋子个数,并输出所有达到最多棋子个数的可能中相同位置的棋子个数
代码:
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int n,m;
int fa[105],vis[105];
int x[10005],y[10005];
int s[105][105],op[105][105];
int dfs(int S){int i,j;for(i=1;i<=m;i++){if(vis[i]==0&&s[S][i]&&op[S][i]==0){vis[i]=1;if(fa[i]==-1||dfs(fa[i])){fa[i]=S;return 1;}}}return 0;
}
int main(){int i,j,k,ans,sum,cas=1,tmp;while(scanf("%d%d%d",&n,&m,&k)!=EOF){memset(s,0,sizeof(s));for(i=1;i<=k;i++){scanf("%d%d",&x[i],&y[i]);s[x[i]][y[i]]=1;}ans=sum=0;memset(op,0,sizeof(op));memset(fa,-1,sizeof(fa));for(i=1;i<=n;i++){memset(vis,0,sizeof(vis));if(dfs(i))ans++;} //把行和列变成点,能放的点就把行和列连起来for(i=1;i<=k;i++){ //求二分图最大匹配就是最多能放的棋子数,这memset(fa,-1,sizeof(fa)); //还是比较基础的,但是在于怎么求相同的点的op[x[i]][y[i]]=1; //个数,因为每一条边相当于一个点,我们可以tmp=0; //枚举删除每一条边,看二分图匹配的值是否会变for(j=1;j<=n;j++){ //这题数据比较水,用匈牙利的话复杂度是O(n*k*k)memset(vis,0,sizeof(vis)); //用网络流的话复杂度可以变为O(n*k*log(k))if(dfs(j))tmp++;}if(tmp!=ans)sum++;op[x[i]][y[i]]=0;}printf("Board %d have %d important blanks for %d chessmen.\n",cas++,sum,ans);}return 0;
}
这篇关于hdu1281(匈牙利算法)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!