並查集的一般操作 ④
阿新 • • 發佈:2018-02-07
利潤 分享圖片 gpo 不能 poj hid return %d mes
RT
並查集一般操作最後一篇
原題 POJ1456
翻譯:
給定N個商品,每個商品有利潤Pi和過期時間di,每天只能賣一個商品,過期商品不能在賣,求如何安排每天買的商品,可以使收益最大。1≤N,pi,di≤10000.
發現,好像可以用貪心的想,從先要過期的商品中賣出利潤大的;
就可以按時間排個序,然後依次按價格放入二叉堆中,每次用大的替換利潤低的;
可以,不過這次想用另一種貪心策略。
我先賣利潤大的商品,並且盡可能晚地賣出;
哦?... interesting!
然後
我們就可以按利潤排序,然後建立一個關於天數的並查集;
什麽意思?就這個意思:
對於每個商品,若它在d天只有過期,就在並查集中查詢d的根R,若R大於0,則安排在第R天賣出,然後把R並到R-1上(還是不懂可以手動模擬)
多思考。
#include <cstdio> #include <algorithm> using namespace std; struct b { int fa[10010]; inline void be(int n){for(int i=0;i<=n;++i)fa[i]=i;return;} int f(int x){return fa[x]=fa[x]==x?x:f(fa[x]);} int u(int x,int y){return fa[f(y)]=f(x)-1;} //把R並到R-1上 }a; int n; structView Coded { int day,val; friend bool operator < (d a,d b) { return a.val > b.val; } }num[10010]; int ans; int main() { // freopen("in","r",stdin); while(scanf("%d",&n)==1) { a.be(10005); for(int i=0;i<n;++i) { scanf("%d%d",&num[i].val,&num[i].day); } sort(num,num+n); //按利潤排序 for(int i=0;i<n;++i) { int root=a.f(num[i].day); if(root>0) //如果有時間就賣 { //printf("%d\n",a.f(num[i].day)); a.u(num[i].day,num[i].day); ans+=num[i].val; } } printf("%d\n",ans); ans=0; } }
11:34:22 2018-02-07
並查集的一般操作 ④