题目链接
关键点:
1、题意:该题给出一个经过hashing处理过的数组,要我们求原来数组的输入顺序
2、该题的hashing处理矛盾的策略为线性探测,求位置:
首先求出这个数对于所有个数的余数,如果该位置满了,就往下找直到找到空位置为止
3、仔细思考,发现其实这个过程类似于拓扑排序的过程
观察题目给出的数组,如果该数除以总数等于所在的下标,那么可以将该点看出入度为0,也就是要先输出
如果不为下标,那么其入度可以算成其下标与余数的差,有一个细节
indegree[i] = (i-index+n)%n;
4、接下来处理连接点,因为只要该点与余数(下标)的点之间的点输出,那么该点的入度就可以减去一,所以我们将该点到余数(包括)的下标间的两点标记为连接,接下来就是拓扑排序的方式输出
完整代码:
# include <iostream>
# include <algorithm>
# include <cstdio>
# include <queue>
# include <vector>
using namespace std;
const int maxn = 1010;
const int inf = 9999999;
vector<int> indegree;
bool visit[maxn];
int e[maxn][maxn];
int a[maxn];
int n;
void topsort()
{
queue<int> q;
for (int i=0; i<n; i++)
{
int u = -1, minn = inf;
for (int j=0; j<n; j++)
{
if (visit[j]==false&&!indegree[j])
{
if (minn>a[j])
{
minn = a[j];
u = j;
}
}
}
if (u==-1) break;
visit[u] = true;
q.push(a[u]);
for (int j=0; j<n; j++)
{
if (visit[j]==false && e[u][j])
{
e[u][j] = 0;
indegree[j]--;
}
}
}
int flag = 0;
while (!q.empty())
{
if (q.front()!=-1)
{
if (!flag)
{
cout<<q.front();
q.pop();
flag = 1;
}
else
{
cout<<" "<<q.front();
q.pop();
}
}
else
{
q.pop();
}
}
}
int main()
{
fill(e[0], e[0]+maxn*maxn, 0);
cin>>n;
indegree.resize(n);
for (int i=0; i<n; i++)
cin>>a[i];
for (int i=0; i<n; i++)
{
if (a[i]==-1)
continue;
int index = a[i]%n;
if (index != i)
{
indegree[i] = (i-index+n)%n;
for (int j=0; j<indegree[i]; j++)
{
e[(j+index)%n][i] = 1;
}
}
}
topsort();
return 0;
}