D - 棋盘游戏(二分图匹配&删边)
思路:匈牙利算法计算原始最大匹配,然后遍历去掉每条边判断一下是否最大匹配变小,若变小即该点为 i m p o r t a n t p o i n t s important\quad points importantpoints。
时间复杂度:
O
(
n
3
)
O(n^3)
O(n3)
p
s
:
ps:
ps:一个奇怪的地方,
N
N
N开到
105
105
105还会
W
A
WA
WA,开到
205
205
205才
A
C
AC
AC。
AC代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<utility>
using namespace std;
const int N=205;
int g[N][N],vis[N],mh[N],n,m,k;
pair<int,int>p[N];
void init(){
for(int i=1;i<N;i++) vis[i]=mh[i]=0;
memset(g,0,sizeof g);
}
int find(int u){
for(int i=1;i<=m;i++)
if(g[u][i]&&!vis[i]){
vis[i]=1;
if(!mh[i]||find(mh[i])){
mh[i]=u;
return 1;
}
}
return 0;
}
int fun(){
int ans=0;memset(mh,0,sizeof mh);
for(int i=1;i<=n;i++){
memset(vis,0,sizeof vis);
ans+=find(i);
}
return ans;
}
int main(){
int kase=0;
while(~scanf("%d%d%d",&n,&m,&k)){
init();
for(int i=1;i<=k;i++){
int x,y;
scanf("%d%d",&x,&y);
g[x][y]=1;
p[i]={x,y};
}
int sum=fun(),cnt=0;
for(int i=1;i<=k;i++){ //判断 important points 只需删该边再计算最大匹配是否变小.
g[p[i].first][p[i].second]=0;
if(fun()<sum) cnt++;
g[p[i].first][p[i].second]=1;
}
printf("Board %d have %d important blanks for %d chessmen.\n",++kase,cnt,sum);
}
return 0;
}