首先将所有点按纵坐标从小到大排序,纵坐标相同的按横坐标从小到大排序,这样一来,每个点+x方向上最近的点(若存在)在排序后的数组宏一定相邻。
DFS搜索与当前点匹配的点,若当前点已经配对,则搜下一个点;若没有配对,则寻找还没有配对的点与当前点配对。
之后分别以每个点为起点进行DFS判环(每次判环前需要清空标记数组),判断是否会重复访问某一节点。注意走到虫洞时,应该立马传送到到与该虫洞配对的点上,而不能停留在这个点。
注意点
- 贝茜会一直沿着 x 轴正向移动,但是她当前的位置约翰并不清楚,所以需要枚举以所有点为起点进行判环。
- 贝茜一旦遇到虫洞则必须进入。
- 虫洞间是无向边,而每个点与+x方向最近的点间是有向边,但稍加分析后会发现,如果上一次是从虫洞走来的,这次必然步行;如果上一次是步行来的,这次必然走虫洞。
const int N=15;
PII a[N];
int r[N],paired[N];
bool vis[N];
int n;
int ans;
bool cycle(int u)
{
if(vis[u]) return true;
vis[u]=true;
if(r[u]) return cycle(paired[r[u]]);
else return false;
}
void dfs(int u)
{
if(u > n)
{
bool ok=false;
for(int i=1; i <= n; i++)
{
memset(vis,0,sizeof vis);
if(cycle(i))
{
ok=true;
break;
}
}
if(ok) ans++;
return;
}
if(paired[u]) dfs(u+1);
else
{
for(int i=u+1; i<=n; i++)
if(!paired[i])
{
paired[u]=i,paired[i]=u;
dfs(u+1);
paired[u]=paired[i]=0;
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i].fi>>a[i].se;
sort(a+1,a+n+1,[](PII a, PII b){
if(a.se != b.se) return a.se < b.se;
return a.fi < b.fi;
});
for(int i=1;i<n;i++)
if(a[i].se == a[i+1].se)
r[i]=i+1;
dfs(1);
cout<<ans<<endl;
//system("pause");
return 0;
}