Data Structures and Algorithms (English) - 7-18 Hashing - Hard Version(30 分)
阿新 • • 發佈:2018-11-14
題目連結:點選開啟連結
題目大意:利用線性探測衝突建立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; }