3 3 4 1 2 1 3 2 1 2 2 3 3 4 1 2 1 3 2 1 3 2
Board 1 have 0 important blanks for 2 chessmen. Board 2 have 3 important blanks for 3 chessmen.
由于是中文题,在题意上小编就不在赘述,题目也是一个简单的二分图题目,可能有童鞋不理解这个图是怎么和二分图扯上关系的,这里小编引用一位大神的话:“如果对一个二维图的处理和整行整列有关系的话,那么多半可以用二分图进行处理”。二分图的题其实大多数都不是难在匈牙利算法上,而是在图的建立上,因为此题在对图的处理上达到了整行整列的处理(车可以走一行),那么此图的两大集合我们就可以分为横坐标和纵坐标。以横纵坐标来建立我们的二分图,然后求出最大匹配,再逐个边删除,求出删除后的最大匹配是否与原来相等。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 100+10; int uN,vN; int g[maxn][maxn],linker[maxn],point[maxn*maxn][2]; bool used[maxn]; bool dfs(int u) { int v; for(v=1; v<=vN; 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() { int res = 0; int u; memset(linker,-1,sizeof(linker)); for(u=1; u<=uN; u++) { memset(used,0,sizeof(used)); if(dfs(u)) res++; } return res; } int main() { int k,u,v,Case=0; while(scanf("%d%d%d",&vN,&uN,&k)!=EOF) { memset(g,0,sizeof(g)); for(int i=1; i<=k; i++) { scanf("%d%d",&u,&v); g[u][v] = 1; point[i][0] = u; point[i][1] = v; } int ans = hungary(); int count=0; for(int i=1; i<=k; i++) { g[point[i][0]][point[i][1]] = 0; int tem = hungary(); g[point[i][0]][point[i][1]] = 1; if(tem != ans) count++; } printf("Board %d have %d important blanks for %d chessmen.\n",++Case,count,ans); } return 0; }