题意:
中文题面就不多说了。。
题解:
类似于最小点覆盖问题,跑一遍最大匹配就好了,还有第二问,可以考虑枚举删掉格子,看最大匹配数是否会变
#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<map>
#include<unordered_map>
#include<set>
#include<vector>
#include<stack>
#include <utility>
#include<algorithm>
#include<cstdio>
#include<list>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<time.h>
#define PI acos(-1.0)
#define eps 1e-9
#define lowbit(a) ((a)&-(a))
const int mod = 1e9+7;
using namespace std;
inline int read(){
char c=getchar();int x=0,s=1;
while(c<'0'||c>'9'){if(c=='-')s=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*s;
}
int qpow(int a,int b){
int ans=1;
while(b){
if(b&1)ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
//#define endl '\n'
const int INF = 0x3f3f3f3f;
const int N = 6e2+5;
const int maxn = 1e3+10;
int g[205][205];
int linker[205],linker2[205],vis[205];
int n,m,ans,num,k;
int find(int u){
for(int i=1;i<=m;i++){
if(!vis[i]&&g[u][i]){
vis[i]=1;
if(linker[i]==-1||find(linker[i])){
linker[i]=u;
return 1;
}
}
}
return 0;
}
int solve(){
memset(linker,-1,sizeof linker);
int ans=0;
for(int i=1;i<=n;i++){
memset(vis,0,sizeof vis);
if(find(i))ans++;
}
return ans;
}
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int cs=0;
while(cin>>n>>m>>num){
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)g[i][j]=0;
for(int i=1;i<=num;i++){
int u,v; cin>>u>>v;
g[u][v]=1;
}
int maxx=solve();
for(int i=1;i<=n;i++){
linker2[i]=linker[i];
}
int ans=0;
for(int v=1;v<=n;v++){
if(linker2[v]==-1)continue;
int u=linker2[v];
g[u][v]=0;
int x=solve();
if(x!=maxx)ans++;
g[u][v]=1;
}
cout<<"Board "<<++cs<<" have "<<ans<<" important blanks for "<<maxx<<" chessmen."<<endl;
}}