1. 程式人生 > >Supermarket 【POJ - 1456】【並查集+雜湊表思想+貪心】

Supermarket 【POJ - 1456】【並查集+雜湊表思想+貪心】

題目連結


  原來,並查集還有這樣的作用——題記。

  我想用個雜湊表的思維來解這道題,但是,顯然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;
}