膜拜了题解后写的,我是用的倒序匹配,如果想知道该怎么做,推荐看看这份题解。
CODE:
/*
PROGRAM: $PROGRAM
AUTHOR: Su Jiao
DATE: 2010-5-13
DESCRIPTION:
$DESCRIPTION
*/
#include <cstdio>
using std::FILE;
using std::fopen;
using std::fclose;
using std::fscanf;
using std::fprintf;
#include <cstring>
using std::memset;
class Application
{
static const int MAXN=10000;
static const int MAXDEGREE=2;
static const int NOTMATCHED=-1;
FILE* in;
FILE* out;
int N;
int D[MAXN];
int degree[MAXN];
int edge[MAXN][MAXDEGREE];
int match[MAXN*2];
bool visited[MAXN*2];
void addEdge(int u,int v)
{
edge[u][degree[u]++]=v+N;
}
void build_graph()
{
for (int i=0;i<N;i++)
{
int n=(i+D[i])%N;
int m=(i-D[i]+N)%N;
if (n==m) addEdge(i,n);
else if (n<m)
{
addEdge(i,n);
addEdge(i,m);
}
else if (n>m)
{
addEdge(i,m);
addEdge(i,n);
}
}
}
bool find(int x)
{
for (int i=0,y;i<degree[x];i++)
if (!visited[y=edge[x][i]])
{
visited[y]=true;
if (match[y]==NOTMATCHED||find(match[y]))
{
match[x]=y;
match[y]=x;
return true;
}
}
return false;
}
public:
Application(const char* input,const char* output)
:in(fopen(input,“r”)),out(fopen(output,“w”))
{
fscanf(in,“%d”,&N);
for (int i=0;i<N;i++) fscanf(in,“%d”,D+i);
memset(degree,0,sizeof(degree));
memset(match,NOTMATCHED,sizeof(match));
}
~Application()
{
fclose(in);
fclose(out);
}
int run()
{
build_graph();
for (int i=N;memset(visited,0,sizeof(visited)),i–;)
if (!find(i))
{
fprintf(out,“No Answer\n”);
return 0;
}
for (int i=0;i<N;i++)
fprintf(out,“%d%c”,match[i]-N,i+1==N?’\n’:’ ‘);
return 0;
}
};
int main()
{
Application app(“transform.in”,“transform.out”);
return app.run();
}