题目链接:HDU - 1281
将点的行缩为一个点,列缩为一个点,那么一个点就可以抽象为一条边。本题可以用行匹配列,一行或一列不能有多个匹配。那么为题就转化成了二分图匹配问题。先计算出图的最大匹配,然后每次删一个点,判断最大匹配是否减少,如果减少那么这个点就是一个重要点。
代码:
#include<stdio.h> #include<string.h> #include<algorithm> #include<vector> using namespace std; typedef long long ll; #define inf 0x3f3f3f3f #define MAXN 110 int k,n,m; int match[MAXN]; bool used[MAXN]; int G[MAXN][MAXN]; bool find(int u) { for(int i=1;i<=m;i++) { if(G[u][i] && !used[i]) { used[i]=1; if(!match[i] || find(match[i])) { match[i]=u; return true; } } } return false; } void init() { memset(match,0,sizeof match); memset(G,0,sizeof G); } int hungry() { int ans=0; for(int i=1;i<=n;i++) { memset(used,0,sizeof used); if(find(i)) ans++; } return ans; } int main() { int cas=1; while(~scanf("%d%d%d",&n,&m,&k)) { init(); for(int i=0;i<k;i++) { int u,v; scanf("%d%d",&u,&v); G[u][v]=1; } int maxx=hungry(),ans=0; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(G[i][j]) { G[i][j]=0; memset(match,0,sizeof match); if(hungry()<maxx) ans++; G[i][j]=1; } } } printf("Board %d have %d important blanks for %d chessmen.\n",cas++,ans,maxx); } return 0; }