HRBUST 1492 盒子 点击打开链接
中文题意,简洁明了。
大致思路:
果然,二分图构建很不好想,但是想到了,自然就柳暗花明了。
我们这样想,只要匹配到一次,那么一定会有个盒子被装进另一个盒子中,也就意味中有一个盒子不见了,那么我们求出最大匹配数,也就找到最多个““不见得盒子”,用总数减去这些盒子,剩下的就是最少能看见的了。。。
代码:
//匹配成功一次,代表有个盒子被藏到另一个盒子中,等价于这个盒子“不见了”,所以最后用总数减去所有匹配数,剩下的就是能看见的盒子。
//匈牙利bfs实现
#include<stdio.h>
#include<iostream>
#include<queue>
#include<vector>
#include<string.h>
using namespace std;
int pre[300000],vis[505];
int ml[300000],mr[300000];
int a[300000];
vector<int>V[300000];
int MaxMatch(int n)
{
int ans=0;
memset(vis,0,sizeof(vis));
memset(ml,-1,sizeof(ml));
memset(mr,-1,sizeof(mr));
for(int i=1; i<=n; i++)
{
if(ml[a[i]]==-1)
{
queue<int>Q;
Q.push(a[i]);
pre[a[i]]=-1;
int flag=0;
while(!Q.empty()&&!flag)
{
int v=Q.front();
Q.pop();
for(int j=0; j<V[v].size()&&!flag; j++)
{
int to=V[v][j];
if(vis[to]!=a[i])
{
vis[to]=a[i];
Q.push(mr[to]);
if(mr[to]>=0)
{
pre[mr[to]]=v;
}
else
{
flag=1;
int d=v;
int e=to;
while(d!=-1)
{
int temp=ml[d];
ml[d]=e;
mr[e]=d;
e=temp;
d=pre[d];
}
}
}
}
}
if(flag)ans++;
}
}
return ans;
}
int main()
{
int m,n;
while(~scanf("%d%d",&m,&n))
{
for(int i=0; i<=300000; i++)V[i].clear();
int b;
for(int i=1; i<=n; i++)
{
scanf("%d%d",&a[i],&b);
V[a[i]].push_back(b);
}
int ans=MaxMatch(n);
printf("%d\n",m-ans);
}
}