题目

Given a hash table of size N, we can define a hash function H(x)=x%N. Suppose that the linear probing is used to solve collisions, we can easily obtain the status of the hash table with a given sequence of input numbers.

However, now you are asked to solve the reversed problem: reconstruct the input sequence from the given status of the hash table. Whenever there are multiple choices, the smallest number is always taken.

Input Specification:
Each input file contains one test case. For each test case, the first line contains a positive integer N (≤1000), which is the size of the hash table. The next line contains N integers, separated by a space. A negative integer represents an empty cell in the hash table. It is guaranteed that all the non-negative integers are distinct in the table.

Output Specification:
For each test case, print a line that contains the input sequence, with the numbers separated by a space. Notice that there must be no extra space at the end of each line.

Sample Input:

11
33 1 13 12 34 38 27 22 32 -1 21

Sample Output:

1 13 12 21 33 34 38 27 22 32

分析

题目大意:从已经确定的散列表中(解决冲突的方法是“线性探测”),找出输入序列

大体思路是把数与数的关系抽象成一张有向图,再用拓扑排序输出

由例子可以看出,比如 1%11 = 1,12%11 = 1,但是 12 排在 1 的后面存储,说明肯定 1 比 12 先输入,而根据线性探测,12 就该存在第二个位置,而现在第二个位置是 13,说明 13 也肯定比 12 先输入,即只有 1 和 13 输入后 12 才能输入,…, 由此可以建立一张有向图,只有前面的结点输入后,后面的结点才能被输入

再进行拓扑排序,要求按从小到大输出,所以用到了STL的最小堆,但是最小堆存的只是值,还要根据值找回下标,又用到了STL的map

#include<queue>
#include<iostream>
#include<vector>
#include<map>
#define INF -100000
#define MaxVertex 1005
int G[MaxVertex][MaxVertex];
int Indegree[MaxVertex];  // 入度 
int value[MaxVertex];  // 存值 
int N;  // 总值
using namespace std;
priority_queue<int,vector<int>,greater<int> > q;   // 定义最小堆 
map<int,int> m;

// 插入边 
void Insert(){
	for(int i=0;i<N;i++){ 
		if(0 <= value[i]){
			m.insert(pair<int,int>(value[i],i));   // 存下标与值的映射关系 
			int remainder = value[i]%N;  // 余数 
			if(remainder==i)
				Indegree[i] = 0;
			else if(remainder != i){
				Indegree[i] = (i - remainder < 0)?(i - remainder + N):(i - remainder);
				for(int j=remainder;j!=i;j=(j+1)%N)
					G[j][i] = 1;
			}
		}
	}
}

// 初始化图 
void build(){
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
			G[i][j] = INF;
	Insert();
}

// 拓扑排序 
void TopSort(){
	for(int i=0;i<N;i++)
		if(!Indegree[i] && 0 < value[i])
			q.push(value[i]);
	bool flag = true;
	while(!q.empty()){
		int tmpValue = q.top(); 
		int v = m[tmpValue];  // 找回下标 
		q.pop();
		if(flag)
			flag = false;
		else
			cout<<" ";
		cout<<tmpValue;
		for(int w=0;w<N;w++)
			if(G[v][w]!=INF){  // 如果连通 
				if(--Indegree[w]==0)
					q.push(value[w]);
			}
	}
}


int main(){
	cin>>N;
	int i=0;
	for(int i=0;i<N;i++)
		cin>>value[i];
	build();

	TopSort();
	return 0;
}