二分图也做过些,可是这题在比赛时竟然没有看出来,就是标准的二分图匹配啊。反思反思
题目大意:有n户人家,m所别墅,给出各户的人口数,每所别墅所能容纳的人数(每种别墅无限种),现在要求两家合租一户别墅,当且仅当这两家人数之和等于别墅所能容纳的人数,问最多有多少种组合方式。
6 4
1 2 3 4 4 5 //每户人家的数目
6 9 3 5 //每栋别墅所能容纳的人数
最多组合三种,1 和4 2 和3 4和5
代码:
//二分图
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
using namespace std;
set<int>st;
int g[1100][1100];
int a[1100];
int vis[1100];
int mx[1100],my[1100];
int n,m;
int dfs(int u)
{
int v;
for(v=0;v<n;v++)
{
if(g[u][v]==1&&vis[v]==0)
{
vis[v]=1;
if(my[v]==-1||dfs(my[v]))
{
mx[u]=v;
my[v]=u;
return 1;
}
}
}
return 0;
}
int main()
{
int T;
cin>>T;
while(T--)
{
st.clear();
memset(g,0,sizeof(g));
cin>>n>>m;
for(int i=0;i<n;i++)
cin>>a[i];
int b;
while(m--)
{
cin>>b;
st.insert(b);
}
//cout<<"jheje"<<endl;
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
if(st.count(a[i]+a[j]))
{
g[i][j]=1;
g[j][i]=1;
}
}
}
int ans=0;
memset(mx,-1,sizeof(mx));
memset(my,-1,sizeof(my));
for(int i=0;i<n;i++)
{
memset(vis,0,sizeof(vis));
ans+=dfs(i);
}
cout<<ans/2<<endl;
}
return 0;
}
/*
2
6 4
1 2 3 4 4 5
6 9 3 5
3
5 4
1 2 3 4 5
6 9 3 5
2
*/