poj-1456 并查集作链表
题意:
超市里有N个商品. 第i个商品必须在保质期(第di天)之前卖掉, 若卖掉可让超市获得pi的利润. 每天只能卖一个商品. 现在你要让超市获得最大的利润.
题解
测试样例:
样例来源 :🙅:🙅♂
// in.text
0
4
50 2 10 1 20 2 30 1
4
50 2 10 1 15 2 27 1
5
1 3 15 2 5 3 20 2 10 1
7
20 1 2 1 10 3 100 2 8 2 5 20 50 10
10
13 2 18 1 68 10 72 8 11 7 41 2 48 7 15 7 34 1 13 8
//ou.text
0
80
77
40
185
302
错误的思路:
把商品先按照期限由小到大排,再按利润由大到小排,用此排序规则的结构体放到优先队列里去。
错误原因是可能有的期限很晚,但是价值很高。
比如这个样例
5 1 3 15 2 5 3 20 2 10 1
如果按这个错误的思路,那么就是 10+20+5=35
而答案应该是 20+15+5
ac思路:
<一> 用优先队列
🐤 从后面往前面数,
for(int i=m;i>=1;–i) 如果从i这个时刻还有事情能被做,就加入到那个挑选的优先队列中去。
#include "cstdio"
#include "cstring"
#include "algorithm"
#include "queue"
using namespace std;
const int maxn=1e4+10;
struct re
{
int use,p,d;
re (int a=0,int b=0)
{
p=a;d=b;
}
};
bool cmp1(const re &a,const re& b)
{
return a.d<b.d;
}
struct cmp {
bool operator() (const re &a, const re &b) const {
return a.p < b.p;
}
};
re all[maxn];
priority_queue<re,vector<re>,cmp > have;
int main()
{
// freopen("in.text","r",stdin);
int n;
while (scanf("%d",&n)!=EOF)
{
int big=0;
for(int i=1;i<=n;++i) {
scanf("%d %d", &all[i].p, &all[i].d);
big=max(all[i].d,big);
}
sort(all+1,all+1+n,cmp1);
int d=n,ans=0;
while (!have.empty())have.pop();
for(int i=big;i>=1;--i)
{
for(;d>=1;--d)
{
if(all[d].d>=i)have.push(all[d]);
else break;
}
if(!have.empty()) {
ans += have.top().p;
have.pop();
}
}
printf("%d\n",ans);
}
return 0;
}
<二>用并查集
把所有的按利润排列好,这个事情只能在那个时间之前做完,假设都在那个时间做,而那个时间已经做了其他事情,那就只能在那个时间之前做了。显然,这是链表的使用(如果当前被用完了,就前进一个),这是不是就像当前被用完了,就用父亲一样,因此可以用并查集代替链表🌟。
#include "cstdio"
#include "cstring"
#include "algorithm"
#include "queue"
using namespace std;
const int maxn=1e4+10;
struct re
{
int p,d;
};
bool cmp1(const re &a,const re& b)
{
return a.p>b.p;
}
int fa[maxn];
int anc(int a)
{
if(fa[a]==-1)return a;
return fa[a]=anc(fa[a]);
}
re all[maxn];
int main()
{
// freopen("in.text","r",stdin);
int n;
while (scanf("%d",&n)!=EOF)
{
memset(fa,-1, sizeof(fa));
for(int i=1;i<=n;++i) {
scanf("%d %d", &all[i].p, &all[i].d);
}
sort(all+1,all+1+n,cmp1);
int ans=0;
for(int i=1;i<=n;++i)
{
int get=anc(all[i].d);
if(get>0)
{
ans+=all[i].p;
fa[get]=get-1;
}
}
printf("%d\n",ans);
}
return 0;
}