HDU 1281(棋盘游戏)二分匹配+暴力

来源:互联网 发布:网络控制 编辑:程序博客网 时间:2024/04/30 17:46

开始你不敢敲估计是怕暴力超时,其实不会的我直接暴力,安静只用了0ms。我也是醉了。

首先x,y轴的二分匹配,然后把跑出的最大匹配中的边删掉,再跑一遍二分匹配,如果这个结果和原来的不一样说明此点就是题目所说的重要点,然后再把删完的这条边再补回去,然后枚举每一个最大匹配的边。

不要惊讶,就这么简单尴尬

#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int N=100+5;int map[N][N],x[N*N],y[N*N],vis[N],link[N],link1[N];int n,m,k;bool dfs(int x){for(int i=1;i<=m;i++){if(!vis[i]&&map[x][i]){vis[i]=1;if(link[i]==-1||dfs(link[i])){link[i]=x;return true;}}}return false;}bool dfs1(int x){for(int i=1;i<=m;i++){if(!vis[i]&&map[x][i]){vis[i]=1;if(link1[i]==-1||dfs(link1[i])){link1[i]=x;return true;}}}return false;}int main(){int t=1;while(~scanf("%d%d%d",&n,&m,&k)){for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){map[i][j]=0;}}memset(x,0,sizeof(x));memset(link,-1,sizeof(link));for(int i=1;i<=k;i++){scanf("%d%d",&x[i],&y[i]);map[x[i]][y[i]]=1;}int res=0;for(int i=1;i<=n;i++)//第一遍二分匹配跑出最大匹配{if(!x[i]) continue;memset(vis,0,sizeof(vis));if(dfs(i)){res++;}}int ans=0;for(int i=1;i<=m;i++)//第二遍枚举最大二分匹配里面的边{int txt=0;if(link[i]!=-1){map[link[i]][i]=0;//删除memset(link1,-1,sizeof(link1));for(int j=1;j<=n;j++)        {        if(!x[j]) continue;        memset(vis,0,sizeof(vis));        if(dfs1(j))        {        txt++;        }        }        if(txt!=res) ans++;        map[link[i]][i]=1;//切记一定要还原}}printf("Board %d have %d important blanks for %d chessmen.\n",t++,ans,res);}return 0;} 

0 0
原创粉丝点击