您的位置:首页 > 其它

hdu1281 棋盘游戏 二分图最大匹配 枚举

2017-08-31 15:58 375 查看
                          HDU 1281 点击打开链接

大致题意:

有一个n*m的棋盘,现在我们要在一些给定的格子里放“车”。

我们要求两个值:(1)在给定的格子里最多能放“车”的数目。

                             (2)在给定的格子里,假如去掉某个格子,但影响了放“车”的最大数目。我们记它为重要点,我们需要求有几个重要点。

大致思路:

对于(1),我们将给出的格子的x值和y值分成两个集合,然后进行连边。这样就构成了一个二分图,我们求最大匹配,即求出了最多能放“车”的数目。(因为任何一个xi,这行只能放一个“车“,yi也一样,这正符合二分图匹配的性质)。

对于(2)我们枚举每个点,将它在二分图中的边去掉,再求一次最大匹配,看是否和原来的先等,假如不相等的话,代表它是一个重要点。

代码:

#include<stdio.h>
#include<iostream>
#include<vector>
#include<queue>
#include<string.h>
using namespace std;
int pre[200];
int vis[200];
int ml[200],mr[200];
int ma[200][200];
int flag[200];
typedef pair<int,int>Pa;
vector<Pa>V2;
vector<int>V[200];
int n,m,k;
int MaxMatch()
{
int sum=0;
memset(vis,0,sizeof(vis));
memset(ml,-1,sizeof(ml));
memset(mr,-1,sizeof(mr));
for(int i=1;i<=n;i++)
{
if(flag[i]&&ml[i]==-1)
{
queue<int>Q;
Q.push(i);
pre[i]=-1;
int kas=0;
while(!Q.empty()&&!kas)
{
int st=Q.front();
Q.pop();
for(int j=1;j<=m&&!kas;j++)
{
int to=j;
if(vis[to]!=i&&ma[st][to])
{
vis[to]=i;
Q.push((mr[to]));
if(mr[to]>=0)
{
pre[mr[to]]=st;
}
else
{
kas=1;
int d=st,e=to;
while(d!=-1)
{
int temp=ml[d];
ml[d]=e;
mr[e]=d;
d=pre[d];
e=temp;
}
}
}
}
}
if(kas)sum++;
}
}
return sum;
}
int main()
{
int cas=1;
while(~scanf("%d%d%d",&n,&m,&k))
{
V2.clear();
memset(flag,0,sizeof(flag));
memset(ma,0,sizeof(ma));

int r,c;
for(int i=0;i<k;i++)
{

scanf("%d%d",&r,&c);
V2.push_back(make_pair(r,c));
flag[r]=1;
ma[r][c]=1;
}
int maxl=MaxMatch();
int ans=0;
for(int i=0;i<V2.size();i++)
{
ma[V2[i].first][V2[i].second]=0;
if(MaxMatch()<maxl)ans++;
ma[V2[i].first][V2[i].second]=1;
}
printf("Board %d have %d important blanks for %d chessmen.\n",cas++,ans,maxl);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二分图 poj