POJ1456 Supermarket 并查集
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - POJ1456
题意概括
一家超市,要卖出N种物品(每种物品各一个),每种物品都有一个卖出截止日期Di(在该日期之前卖出可以获得收益,否则就无法卖出),且每种物品被卖出都有一个收益值Pi. 卖出每个物品需要耗时1天,且任一时刻只能卖出一个物品。给出这N种物品的Di和Pi,求最大收益值。
题解
堆的做法大概是第一感,闭着眼睛应该都可以想到。
堆的做法:倒着来,对于每一天,如果有产品在当天结束销售,那么把他们扔进堆里面。每天选择最贵的销售。
但是正着来怎么搞??
我们用并查集维护。
先给所有的产品按照价格从大到小排序。
然后对于每一个产品尽量靠后销售。
比如当前产品确定在第x天销售,那么我们就把答案加上去,fa[x]=getf(x-1)。
如果x=0,那么自然不销售,也不做任何操作。
代码
#include <cstring> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cmath> using namespace std; const int N=10005; int n,fa[N]; struct Pro{ int p,d; }p[N]; bool cmp(Pro a,Pro b){ if (a.p==b.p) return a.d>b.d; return a.p>b.p; } int getf(int k){ return fa[k]==k?k:fa[k]=getf(fa[k]); } int main(){ while (~scanf("%d",&n)){ for (int i=1;i<=n;i++) scanf("%d%d",&p[i].p,&p[i].d); sort(p+1,p+n+1,cmp); for (int i=0;i<=10000;i++) fa[i]=i; int ans=0; for (int i=1;i<=n;i++){ int day=getf(p[i].d); if (!day) continue; ans+=p[i].p; fa[day]=getf(day-1); } printf("%d\n",ans); } return 0; }