刚开始用暴力打出每个数字相匹配的那个数字。然后就是运用匈牙利算法进行计算,但是得字典序输出。所以采用倒着使用匈牙利算法。同时存储图的时候由于最大是1000,所以采用vector的邻接表进行存储。
ac代码:(900ms)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<cmath>
#include<cstdlib>
#include<list>
#include<queue>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define MAXN 0x3f3f3f3f3f3f3f3f
#define PI acos(-1.0)
#define E exp(1.0)
using namespace std;
//#define debug
const int maxn=10005;
vector<int> e[maxn];
int vis[maxn];
int boy[maxn];
int a[maxn];
int gril[maxn];
int n;
bool dfs(int v){
for(int i=0;i<n;i++){
if(!vis[i]&&count(e[v].begin(),e[v].end(),i)){
vis[i]=1;
if(boy[i]==-1||dfs(boy[i])){
boy[i]=v;
gril[v]=i;
return 1;
}
}
}
return 0;
}
int main()
{
#ifdef debug
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif // debug
ACCELERATE;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(min(abs(i-j),n-abs(i-j))==a[i]){
e[i].push_back(j);
}
}
}
mm(vis,0);
mm(boy,-1);
int tot=0;
for(int i=n-1;i>=0;i--){
mm(vis,0);
if(dfs(i)) tot++;
}
if(tot!=n){
printf("No Answer\n");
}
for(int i=0;i<n-1;i++){
cout<<gril[i]<<" ";
}
cout<<gril[n-1]<<endl;
return 0;
}
还有一种就是运用嗯二分图匹配,刚开始配对的是i跟j+n,还有j+n跟i,因为匈牙利算法计算的匹配是后面跟前,而现在转为前面跟后面,所以+n这种配对方式有很大优势,而在dfs里面,右边匹配左边先标记的左边,所以左边匹配右边就先标记右边。 同时得用vis判断一下是否会造成循环。因为是两端一起匹配。
ac代码:(200ms)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<cmath>
#include<cstdlib>
#include<list>
#include<queue>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define MAXN 0x3f3f3f3f3f3f3f3f
#define PI acos(-1.0)
#define E exp(1.0)
using namespace std;
//#define debug
const int maxn=10005;
vector<int> e[maxn*2];
int vis[maxn*2];
int match[maxn*2];
int a[maxn*2];
int n;
bool dfs(int v){
vis[v]=1;
for(int i=0;i<e[v].size();i++){
int u=e[v][i],w=match[u];
//printf("%d %d %d %d %d-----\n",v,u,w,vis[w],match[w]);
if(w==-1||!vis[w]&&dfs(match[u])){ //!vis[w] 的意思是因为两端都在匹配,防止造成循环匹配到下面,又匹配到上边。
match[u]=v;
match[v]=u;
return 1;
}
}
return 0;
}
int main()
{
#ifdef debug
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif // debug
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<2*n;i++){
e[i].clear();
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(min(abs(i-j),n-abs(i-j))==a[i]){
e[i].push_back(j+n);
e[j+n].push_back(i);
}
}
}
mm(vis,0);
mm(match,-1);
for(int i=0;i<n;i++){
sort(e[i].begin(),e[i].end());
}
int tot=0;
for(int i=n-1;i>=0;i--){
mm(vis,0);
if(dfs(i)) tot++;
}
if(tot!=n){
printf("No Answer\n");
}
for(int i=0;i<n-1;i++){
printf("%d ",match[i]-n);
}
cout<<match[n-1]-n<<endl;
return 0;
}
/*
10
1 5 4 2 3 1 4 3 1 4
1 6 8 5 7 4 2 0 9 3
*/