HDU1281 棋盘游戏(坐标平面 ,行列匹配+求关键点)

来源:互联网 发布:矩阵论教程 张绍飞pdf 编辑:程序博客网 时间:2024/06/06 09:42

题意:略;
思路:把坐标X看做二分图的左边,Y看做右边,结合二分图的最大匹配,左右顶点形成的最大匹配边,就是不同行不同列。求关键点,就依次枚举删掉某一个边后是否会使匹配变小

#include<iostream>#include<cstdlib>#include<cmath>#include<algorithm>#include<cstring>#include<cstdio>#include<queue>#include<set>#include<stack>#define cl(a,b) memset(a,b,sizeof(a));#define LL long long#define P pair<int,int>#define X first#define Y second#define pb push_backusing namespace std;const int maxn=150;const int inf=9999999;const int mod=100007;int G[maxn][maxn];int x[maxn*maxn],y[maxn*maxn];int matching[maxn];bool vis[maxn];int n,m,k;bool dfs(int u){    for(int i=0;i<m;i++)if(G[u][i]){        int v=i;        if(vis[v])continue;        vis[v]=true;        if(matching[v]==-1||dfs(matching[v])){            matching[v]=u;            return true;        }    }    return false;}int hungar(){    int ans=0;    cl(matching,-1);    for(int i=0;i<n;i++){        cl(vis,false);        if(dfs(i))ans++;    }    return ans;}int main(){    int cas=1;    while(~scanf("%d%d%d",&n,&m,&k)){        cl(G,0);        for(int i=0;i<k;i++){            scanf("%d%d",&x[i],&y[i]);            x[i]--;y[i]--;            G[x[i]][y[i]]=1;        }        int ans=0;        int mx=hungar();       // printf("===%d\n",mx);        for(int i=0;i<k;i++){            G[x[i]][y[i]]=0;//删除            if(hungar()<mx)ans++;            G[x[i]][y[i]]=1;//复原        }        printf("Board %d have %d important blanks for %d chessmen.\n",cas++,ans,mx);    }    return 0;}
0 0