二分图最大匹配,有点小注意就可以。
这里gopher和hole就是二分图的两个集合了。
但是两个集合之间的边不是它告诉你的,而是需要你自己判断两点之间有没有的。
比较裸题了……希望我也能匹配到能温柔地牵着我的手一起走的女孩。跑题了哈哈。
AC代码
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn=1e2+10;
struct coodinate
{
double x,y;
}goph[maxn],hole[maxn];
int n,m,s,v;
double getdis(coodinate a,coodinate b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int mate[maxn];
bool used[maxn];
bool Findm(int x)
{
for(int i=1;i<=m;i++)
{
if(!used[i]&&getdis(goph[x],hole[i])<=double(s*v))//这个getdis就是判断两点有没有边的函数
{
used[i]=1;
if(!mate[i]||Findm(mate[i]))
{
mate[i]=x;
return 1;
}
}
}
return 0;
}
int main()
{
while(scanf("%d%d%d%d",&n,&m,&s,&v)==4)
{
memset(goph,0,sizeof(goph));
memset(hole,0,sizeof(hole));
for(int i=1;i<=n;i++)
scanf("%lf%lf",&goph[i].x,&goph[i].y);
for(int i=1;i<=m;i++)
scanf("%lf%lf",&hole[i].x,&hole[i].y);
int safe=0;
memset(mate,0,sizeof(mate));
for(int i=1;i<=n;i++)
{
memset(used,0,sizeof(used));
safe+=Findm(i);
}
printf("%d\n",n-safe);
}
}
另外一个转化的问题就是poj 3041的。
转化思想:每行的行序号是集合A,每列的列序号是集合B,asteroid就是连接所在行列序号的边。
因为每一个asteroid都要被消灭,而Bessie又是整行整列的消灭,所以每一个asteroid要么被行消灭,要么被列消灭,至少有一个。
转化到图上也就是每一条边至少有一个点和它相连——即最小点覆盖集。
这样子建的图一定是二分图……比较显然吧?
那就可以用最大二分匹配做。