题目大意
给定一个长度为n的排列
∙构造一个n个点的图,当第
输出任意一种方案即可,数据保证有解。
题目分析
显然我们先将所有(i,Pi)连上会形成若干个互不连通的简单环,一个简单环只要确定了一个点是左还是右就能确定整个环的状态。那么我们显然可以搜索加判断,因为每个环最小大小是2,所以复杂度是
考虑怎么优化,可以发现大小为2的环其实可以直接根据先后顺序确定填什么。那么我们直接特判掉大小为
代码实现
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
const int N=105;
int P[N],fa[N],rank[N];
bool seq[N],cet[N];
int n;
int getfather(int son){return fa[son]==son?son:fa[son]=getfather(fa[son]);}
inline int merge(int x,int y)
{
if (rank[x]>rank[y]) swap(x,y);
fa[x]=y,rank[y]+=rank[x]==rank[y];
}
inline void go(int x){for (int y=P[x],c=seq[x];x!=y;c=seq[y]=c^1,cet[y]^=1,y=P[y]);}
bool dfs(int x,int sum)
{
if (sum<0) return 0;
if (x==n+1) return !sum;
if (!cet[x])
{
/*if (seq[x]=0,go(x),dfs(x+1,sum+(seq[x]?-1:1))) return 1;
go(x);
if (P[P[x]]==x) return 0;
if (seq[x]=1,go(x),dfs(x+1,sum+(seq[x]?-1:1))) return 1;
return go(x),0;*/
for (int c=0,y,z,cnt;c<2;++c)
{
for (cnt=1,z=seq[x]=c,y=P[x];x!=y;z=seq[y]=z^1,cet[y]=1,y=P[y],++cnt);
if (dfs(x+1,sum+(seq[x]?-1:1))) return 1;
if (cnt==2) return 0;
}
for (int y=P[x];x!=y;y=P[y],cet[y]=0);
return 0;
}else return dfs(x+1,sum+(seq[x]?-1:1));
}
int main()
{
freopen("wall.in","r",stdin),freopen("wall.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;++i) fa[i]=i;
for (int i=1;i<=n;++i)
{
scanf("%d",&P[i]);
int fx=getfather(i),fy=getfather(P[i]);
if (fx!=fy) merge(fx,fy);
}
dfs(1,0);
for (int i=1;i<=n;++i) putchar(seq[i]?')':'(');
printf("\n");
fclose(stdin),fclose(stdout);
return 0;
}