原题地址:点击打开链接
题意,给你两个集合A,和B,问你最少删除集合A和B中的几个数才能使得集合B中不存在可以整除集合A中的数,
将该题转换为二分图的最大匹配问题即可,集合A为左边的点,集合B为右边的点,如果B集合中的某个数可以整除A集合
中的某个数则连一条边,如何才能使得A,B之间不存在这种整除关系呢,我们找出最小顶点覆盖即可,(最小顶点覆盖就是
最小的顶点数集合V,能使该图中每一条边都至少有一个顶点属于V)如果将最小顶点覆盖数删除,则图中所有的边都将不存在,
意思就是不在存在这种整除关系。 在二分图中,最大匹配数等于最小顶点覆盖数,在这里我就不证明了,有兴趣可以去百度一下。
#include<stdio.h>
#include<vector>
#include<string.h>
using namespace std;
int setA[110],setB[110];
vector<int>g[110];
int match[110];
int used[110];
bool find(int u) //找寻增广路
{
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(!used[v])
{
used[v]=1;
if(match[v]==-1||find(match[v]))
{
match[v]=u;
return true;
}
}
}
return false;
}
int max_match(int n)
{
int res=0;
memset(match,-1,sizeof(match));
for(int i=1;i<=n;i++)
{
memset(used,0,sizeof(used));
if(find(i))
res++;
}
return res;
}
int main()
{
int t,n,m,i,j,k=0;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&setA[i]);
scanf("%d",&m);
for(i=1;i<=m;i++)
scanf("%d",&setB[i]);
for(i=1;i<=n;i++)
g[i].clear();
for(i=1;i<=n;i++) //建图
{
for(j=1;j<=m;j++)
{
if(setB[j]%setA[i]==0) //如果能整除则建边
g[i].push_back(j);
}
}
int res=max_match(n);
printf("Case %d: %d\n",++k,res);
}
return 0;
}