1. 程式人生 > >Data Structures and Algorithms (English) - 7-18 Hashing - Hard Version(30 分)

Data Structures and Algorithms (English) - 7-18 Hashing - Hard Version(30 分)

題目連結:點選開啟連結

 

題目大意:利用線性探測衝突建立Topo圖,用Topo排序輸出(多個 in[i]==0,輸出結點值較小的那個)。

 

解題思路:關鍵在於建Topo圖遇到衝突時,不是一開始建造的時候位置都為空,而是一開始的時候位置就是Input的位置已經佔著了的,以後者規則為基準。因為 int 值可能很大,所以使用 unordered_map 來替換。

如題目中的樣例,假設題目中的元素在一個ha[11]的陣列中

33 % 11 = 0,ha[0] = 33 ,因此什麼事都不做;

1 % 11 = 1,ha[1] = 1, 同上;

13 % 11 = 2,ha[2] = 13, 同上;

12 % 11 = 1,ha[1] != 12,說明發生了衝突,此時1和13一定在12之前進入雜湊表(因為線性探測法是逐個向後找空位),所以建立<1,12>、<13, 12>這兩條有向邊來表明先後順序;

……// 後面的都類似;

而32 % 11 = 10,ha[10] != 32,又發生了衝突,而此時已經是表的末尾,因此只能重新回到0號位依次探測空位直到8號位,因此需要建立<21, 32>、<33, 32>、<1, 32>...<22, 32>這些有向邊

以上步驟是根據雜湊表來建立一個有向圖。其中建立有向圖時,結點我選擇的是用下標來表示(因為不知道元素的大小),不過還是用了個 unordered_map 陣列來記錄下標。

然後就是根據有向圖來做一個拓撲排序,排序的時候使用優先佇列容器來儲存入度為0的元素,方便找到最小的元素。

 

AC 程式碼

#include<bits/stdc++.h>
#include<cmath>

#define mem(a,b) memset(a,b,sizeof a)
#define ssclr(ss) ss.clear(), ss.str("")
#define INF 0x3f3f3f3f
#define MOD 1000000007

using namespace std;

typedef long long ll;

const int maxn=1009;

int n;
int ha[maxn], in[maxn], g[maxn][maxn];
unordered_map<int,int> ump, id;
vector<int> vec;
priority_queue<int,vector<int>,greater<int>> pq;

void topo()
{
    for(int i=1;i<=n;i++)
        if(in[i]==0 && ump[i]>=0) pq.push(ump[i]); // avoid 負數的情況

    while(!pq.empty())
    {
        int tp=pq.top(); pq.pop();
        vec.push_back(tp);
        for(int i=1;i<=n;i++)
            if(g[id[tp]][i] && --in[i]==0)
                pq.push(ump[i]);
    }
}

int main()
{
    int num,p,pos;
    scanf("%d",&n);
    p=n;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&num);
        ump[i]=num;
        id[num]=i;
        ha[i-1]=i;
    }

    for(int i=1;i<=n;i++)
    {
        if(ump[i]<0) continue;
        for(int j=0;;j++)
        {
            pos=(ump[i]+j)%p;
            if(ha[pos]==i || ump[ha[pos]]<0) break;
            g[ha[pos]][i]=1;
            in[i]++;
        }
    }

    topo();

    for(int i=0;i<vec.size();i++)
        printf("%d%c",vec[i],i==vec.size()-1?'\n':' ');

    return 0;
}