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;
}