https://www.lydsy.com/JudgeOnline/problem.php?id=1562
既然要字典序最小,我们知道匈牙利算法是一找到增广路就迅速转边的。
所以我们每个点的出边需要从大到小,且需要从后往前跑匈牙利,因为前面优先选择最小的边,已找到就迅速转边,不管后面之前已经匹配过的点,怎么匹配。
#include<bits/stdc++.h>
using namespace std;
const int maxl=1e4+10;
int n,m,tot,ans;
int vis[maxl],match[maxl],dy[maxl];
vector<int> e[maxl];
inline void prework()
{
scanf("%d",&n);
int d;
for(int i=0;i<n;i++)
{
scanf("%d",&d);
if(i-d>=0)
e[i].push_back(i-d);
if(i+d<n)
e[i].push_back(i+d);
d=n-d;
if(i-d>=0)
e[i].push_back(i-d);
if(i+d<n)
e[i].push_back(i+d);
sort(e[i].begin(),e[i].end());
}
}
inline bool dfs(int u)
{
int v,l=e[u].size();
for(int i=0;i<l;i++)
{
v=e[u][i];
if(vis[v]!=tot)
{
vis[v]=tot;
if(!match[v] || dfs(match[v]))
{
match[v]=u;
return true;
}
}
}
return false;
}
inline void mainwork()
{
ans=0;
for(int i=n-1;i>=0;i--)
{
++tot;
if(dfs(i))
ans++;
}
}
inline void print()
{
if(ans!=n)
puts("No Answer");
else
{
for(int i=0;i<n;i++)
dy[match[i]]=i;
for(int i=0;i<n;i++)
printf("%d%c",dy[i],(i==n-1)?'\n':' ');
}
}
int main()
{
prework();
mainwork();
print();
return 0;
}