距离NOIP2017还有7天,那么我们就准备一些模板来看看吧!
今天复习一下匈牙利算法!
值得一提的是,匈牙利算法求出的二分图最大匹配就是最小点覆盖。这样我们可以做一个“战略游戏”(Luogu P2016)的题目。
模板的具体解释见代码:(Luogu P3386)
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int i,j,k,m,n,e;
int hd[2001],temp;
int mat[2001],b[2001];
int ans;
struct data
{
int y,nxt;
}a[2000001];
int r()
{
int aans=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
aans*=10;
aans+=ch-'0';
ch=getchar();
}
return aans*f;
}
void add(int xx,int yy)
{
a[++temp].y=yy;
a[temp].nxt=hd[xx];
hd[xx]=temp;
}
bool dfs(int x)
{
for(int p=hd[x];p;p=a[p].nxt)
{
int son=a[p].y;
if(!b[son])
{
b[son]=1;//是否遍历过
if(!mat[son]||dfs(mat[son]))//如果目标搭档没有搭档或者目标搭档可以被抢走
{
mat[son]=x;//那么把让这两个成为一对
mat[x]=son;
return 1;//返回当前可行
}
}
}
return 0;//返回不可行
}
int main()
{
// freopen("in.txt","r",stdin);
n=r(),m=r(),e=r();
int u,v;
for(i=1;i<=e;i++)
{
u=r(),v=r();
if(v<=m&&u<=n&&u>0&&v>0)//判断数据
{add(u,v+n);//建双向边
add(v+n,u);}
}
for(i=1;i<=n;i++)
{
if(!mat[i])//是否有搭档
{
memset(b,0,sizeof(b));
if(dfs(i))
ans++;
}
}
cout<<ans;
return 0;
}
/*
3 4 6
1 1
1 2
1 3
2 2
2 4
3 1
3 3
*/