题目链接:
http://www.bnuoj.com/bnuoj/problem_show.php?pid=12756
Social Holidaying
3000ms
131072KB
This problem will be judged on UVALive. Original ID:
5874
64-bit integer IO format: %lld Java class name: Main
64-bit integer IO format: %lld Java class name: Main
Font Size:
Source
题目大意:先输入一个P表示有几组测试数据,再输入一个n,m分别表示A、B集合中分别有多少元素。在A集合中找到多少对数相加=B集合中的元素。A集合中的数不可以重复,但是B集合中的数字可以重复出现。
解题思路:二分匹配。先将A集合中的和的所有可能情况列出来,然后在B集合中搜索即可。
详见代码。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int ss[9999999],Map[410][410];
int ok[410],vis[410];
int a[410],b[410];
int n,m;
bool Find(int x)
{
for (int i=1; i<=n; i++)
{
if (!vis[i]&&Map[x][i]==1)
{
vis[i]=1;
if (!ok[i])
{
ok[i]=x;
return true;
}
else
{
if (Find(ok[i]))
{
ok[i]=x;
return true;
}
}
}
}
return false;
}
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
scanf("%d%d",&n,&m);
int ans=0;
memset(vis,0,sizeof(vis));
memset(Map,0,sizeof(Map));
memset(ok,0,sizeof(ok));
memset(ss,0,sizeof(ss));
for (int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
}
for (int i=1; i<=m; i++)
{
scanf("%d",&b[i]);
ss[b[i]]=1;
}
for (int i=1; i<=n; i++)
{
for (int j=i+1; j<=n; j++)
{
if (ss[a[i]+a[j]]==1)
Map[i][j]=Map[j][i]=1;
}
}
for (int i=1; i<=n; i++)
{
memset(vis,0,sizeof(vis));
if (Find(i))
ans++;
}
printf ("%d\n",ans/2);
}
return 0;
}