UsacoTraining 1.4 Wormholes
http://train.usaco.org/usacoprob2?S=wormhole&a=v6rpnAVebaa
有n个虫洞。将它们两两匹配,从一个可以到另一个。从虫洞出来后,只会向右走(+x方向)。问有多少种匹配方式,使得会出现死循环。
由于n<=12,直接暴力。先递归建边,再判断循环。判断循环有一种舒服的做法:从任意一点,每次到右边最近虫洞的匹配虫洞,跑n次,若到达的虫洞依旧合法,就有环。
注意:y[0]最好设为-1,否则会和其他虫洞的y相同。
#include<bits/stdc++.h>
using namespace std;
struct node{
int x,y;
}a[15];
int n,g[15],ans,next[15];
bool vis[15];
inline bool cmp(node a,node b){
return (a.y==b.y)?a.x<b.x:a.y<b.y;
}
inline bool dfs(){
int x;
for(int i=1;i<=n;++i){
x=i;
for(int j=1;j<=n;++j){
if(a[x].y==a[x+1].y) x=g[x+1];
else x=0;
}
if(x!=0) return 1;
}
return 0;
}
inline void jiantu(int u){
if(u>n){
ans+=dfs();
return;
}
else{
if(!g[u]){
for(int i=u+1;i<=n;++i)
if(!g[i]){
g[u]=i,g[i]=u;
jiantu(u+1);
g[u]=g[i]=0;
}
}
else jiantu(u+1);
}
}
int main()
{
freopen("wormhole.in","r",stdin);
freopen("wormhole.out","w",stdout);
ios::sync_with_stdio(false);cin.tie(0);
cin>>n;
g[0]=0;
a[0].x=a[0].y=-1;
for(int i=1;i<=n;++i) cin>>a[i].x>>a[i].y;
sort(a+1,a+n+1,cmp);
jiantu(1);
cout<<ans<<'\n';
}