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

  

posted @ 2017-12-11 14:24  zzd233  阅读(219)  评论(0编辑  收藏  举报