一开始看错题以为是个傻逼的模拟。。不过也是个二分图匹配,但是我挂了好几次。。
可以弄出每个位置可以放的两个数,然后可以建出二分图。。不过要满足字典序最小,我一开始是边表按to从小到大放,顺序匹配,发现好像不行。。看了网上的说要倒序匹配,想一想也是,如果有解的话后匹配的点其实是优先满足的。。
#include<iostream>
#include<cstdio>
#define N 10005
using namespace std;
int n,i,j,ne=0,m1,m2,t[N],u[N],a[N][2],pre[N],to[N];
bool find(int x,int tim)
{
for (int i=0;i<=1;i++)
if (u[a[x][i]]>tim)
{
u[a[x][i]]=tim;
if (pre[a[x][i]]==0||find(pre[a[x][i]]-1,tim))
{
pre[a[x][i]]=x+1;to[x]=a[x][i];
return true;
}
}
return false;
}
int hungary(int n)
{
for (i=n-1;i>=0;i--)
if (!find(i,i)) return i;
return n;
}
int main()
{
freopen("1562.in","r",stdin);
scanf("%d",&n);
for (i=0;i<n;i++) u[i]=n,pre[i]=0;
for (i=0;i<n;i++)
{
scanf("%d",&t[i]);
m1=(i+t[i])%n;m2=(i-t[i]+n)%n;
if (m1>m2) swap(m1,m2);
a[i][0]=m1;a[i][1]=m2;
}
int ans=hungary(n);
if (ans==n)
{
for (i=0;i<n-1;i++) printf("%d ",to[i]);printf("%d",to[n-1]);
}
else printf("No Answer");
}