hdu 4864

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;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值