http://poj.org/problem?id=1456
A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold by a deadline dx that is measured as an integral number of time units starting from the moment the sale begins. Each product takes precisely one unit of time for being sold. A selling schedule is an ordered subset of products Sell ≤ Prod such that the selling of each product x∈Sell, according to the ordering of Sell, completes before the deadline dx or just when dx expires. The profit of the selling schedule is Profit(Sell)=Σx∈Sellpx. An optimal selling schedule is a schedule with a maximum profit.
题目想法是
先按照价值从大到小排序,把它放在放在他的时间节点上,如果这个时间节点已经被占用,就看他的t-1...1安放
利用并查集优化的思想是初始化并查集-1,看他的父节点是否为-1,-1则返回本身节点时间,本身时间>0,就ans+,然后让它的父节点为t-1;
当我们处理第i个商品的时候,我们正常来说应该是从i的截止时间往前找,看看有没有空闲时间点来放商品i。这样查找的过程比较慢。
这里我们用并查集来做些优化,即对于时间点t来说,如果t时间点空闲,那么fa[t]==-1。 我们用findset(t)查找可行时间点时直接就可以返回t(因为t本来就可行)。如果t时间点不空闲,那么我们令fa[t]==t-1。我们用findset(t)查找可行时间点时返回的(不一定是t-1,如果t-1被占用,返回的就不是t-1。否则返回t-1)是从t-1时间点开始递归查找的结果。
优化思想来自:
原文:https://blog.csdn.net/u013480600/article/details/21102041
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=10000+5;
struct Node//商品
{
int p;//利润
int t;//截止时间
bool operator<(const Node &rhs)const
{
return p>rhs.p;
}
} nodes[maxn];
//findset(t)表示:t时间前的最晚一个可用时间点(可以是t)
int fa[maxn];
int findset(int x)
{
return fa[x]==-1? x:fa[x]=findset(fa[x]);
}
int main()
{
int n;
while(scanf("%d",&n)==1)
{
for(int i=0; i<n; i++)
{
scanf("%d%d",&nodes[i].p,&nodes[i].t);
}
sort(nodes,nodes+n);
//按照价值从大到小排序
memset(fa,-1,sizeof(fa));
int cnt=0;//最终利润
for(int i=0; i<n; i++)
{
//找到i商品截止时间前的最晚一个可用时间点
int time=findset( (nodes[i].t) );//可行;
if(time>0)//时间可行
{
cnt += nodes[i].p;//加上;
fa[time]=time-1;//下车再看nodes[i].t
//这个时间节点是他的父节点就是time-1,不再是它本身
//就是判断他的前一时刻;
}
}
printf("%d\n",cnt);
}
return 0;
}