Supermarket 【POJ - 1456】【並查集+雜湊表思想+貪心】
阿新 • • 發佈:2018-12-25
題目連結
原來,並查集還有這樣的作用——題記。
我想用個雜湊表的思維來解這道題,但是,顯然O(N^2)的雜湊表去查詢並插入顯然是不行的,那麼既然掛在圖論專題,我就得用相應的方式解答咯(要是不掛在圖論專題,我可能會自閉了),我們對於每個物品按照價值降序排列,要的就是價值高的物品先放進雜湊表中,但是,怎麼確定這個點的值是否已經有值了?
我們用到了並查集,對於可以放進雜湊表中的值,相當於,我們可以把他的時間與前一刻的時間連立起來,就是意味著這個點已經用過了,時間到了前面的那個時間(不一定就是前面的時間,是指的是前一個空的時間),用並查集。那麼判斷是否可以用,就是判斷,它的時間點是否可以用,只要前面的還有空位就是可以放進去,時間點不為0就是前面有空位,那麼就是並查集找到的祖先不是0就行了。
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define efs 1e-7 using namespace std; typedef unsigned long long ull; typedef long long ll; const int maxN = 1e4 + 7; int N, root[maxN], sum[maxN], ans; struct node { int val, day; node (int a=0, int b=0):val(a), day(b) {} }a[maxN]; bool cmp(node e1, node e2) { return e1.val == e2.val?(e1.day < e1.day):(e1.val > e2.val); } int fid(int x) { return x == root[x]?x:(root[x] = fid(root[x])); } void mix(int x, int y) { int u = fid(x), v = fid(y); if(u != v) { if(u > v) swap(u, v); root[v] = u; } } void init() { for(int i=0; i<maxN; i++) root[i] = i; memset(sum, 0, sizeof(sum)); ans = 0; } int main() { while(scanf("%d", &N)!=EOF) { init(); for(int i=1; i<=N; i++) { scanf("%d%d", &a[i].val ,&a[i].day); } sort(a+1, a+1+N, cmp); for(int i=1; i<=N; i++) { int x = a[i].day; int u = fid(x); if(u >= 1) { mix(x, u-1); ans += a[i].val; } } printf("%d\n", ans); } return 0; }