100000的数据量,如果用二分图匹配的话边最多有10^10条....Hopcroft-Karp都过不了
那就只能贪心了.
首先发现y很小,才100,而且按照钱的计算方法,x起决定作用
所以可以把tasks按x,y排序,x大的task优先完成
然后就是如何贪心匹配了:
对于task(tx,ty),首先肯定只能找machine(mx>=tx,my>=ty),如果只有一个的话那就直接选(因为每个machin只能用一次,而现在的tast是钱最多的)
如果有多个,见下图:
我们正在为三角task选machin,可选的有三个1,2,3,按常理要么我们选x最接近的3,要么选y最接近的1
如果选3的话:那么在之后的选择中会出现左边那个圆圈(x比较小,y比较大),由于你把3选走了,导致最终结果少匹配了一个,所以是错的
如果选1的话:可以看到右下方有个圆圈...(x比较大,y比较小),你又抢了它的1>_<
但是...由于你是排好序x大的先选,所以右下那个圆圈肯定已经选完了,所以选1是正确的
结论就是:在mx>tx的machine中选一个y值最小的匹配就行。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn=100000+100;
int N,M;
struct Node
{
int x,y;
bool operator<(const Node &a)const
{
if(x==a.x)
return y>a.y;
else return x>a.x;
}
};
multiset<int> mc[110];
Node ts[maxn];
int main()
{
freopen("in.txt","r",stdin);
LL res,cnt;
while(~scanf("%d%d",&N,&M))
{
for(int i=0;i<=100;i++)
mc[i].clear();
cnt=res=0;
Node tn;
for(int i=0;i<N;i++)
{
scanf("%d%d",&tn.x,&tn.y);
mc[tn.y].insert(tn.x);
}
for(int i=0;i<M;i++)
{
scanf("%d%d",&tn.x,&tn.y);
ts[i]=tn;
}
sort(ts,ts+M);
for(int i=0;i<M;i++)
{
for(int y=ts[i].y;y<=100;y++)
{
set<int>::iterator iter= mc[y].lower_bound(ts[i].x);
if(iter!=mc[y].end())
{
res+=ts[i].x*500+ts[i].y*2;
cnt++;
// cout<<*iter<<" "<<y<<endl;
// cout<<ts[i].x<<" "<<ts[i].y<<endl<<endl;
mc[y].erase(iter);
break;
}
}
}
cout<<cnt<<" "<<res<<endl;
}
return 0;
}