版权声明:本文为博主原创文章,转载前动动小手点个【赞】吧~ https://blog.csdn.net/Dream_Weave/article/details/84027385
题目链接:点击打开链接
题目大意:利用线性探测冲突建立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;
}