USACO 1.3 Wormholes
这题卡了我n久时间。。。
Solution:
1. 按照坐标y值排序,同时按x从小到大排序
2. 连边: 纵坐标相同的点从左至右连边;eg: dot1(1,3)dot2(3,3)dot3(5,3)连dot1->dot2,dot2->3
3. DFS选择不同的连边组合,边数达到n/2时判断并结束
4. 输出结果
/*
ID: zzzc181
PROG: wormhole
LANG: C++
*/
#include<ctime>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 30
using namespace std;
struct data{
int x,y,k;
}node[MAXN];
int n,ans;
int vis[MAXN];
int edge1[MAXN],edge2[MAXN];
bool cmp(const data & a, const data & b){
if(a.y!=b.y){
return a.y<b.y;
}
return a.x<b.x;
}
bool check(int x){
memset(vis,0,sizeof(vis));
bool pd=false;
while(1){
vis[x]++;
if(vis[x]>n) return true;
int i;
pd=false;
if(edge1[x]){
x=edge2[edge1[x]];
pd=true;
}
if(!pd) return false;
}
return false;
}
void DFS(int x){
if(x==n/2+1){
int p;
for(p=1;p<=n;p++){
if(check(p)){
ans++;
return;
}
}
return;
}
int i,j;
for(i=1;i<=n;i++){
if(!edge2[i]){
for(j=i+1;j<=n;j++){
if(!edge2[j]){
edge2[i]=j;edge2[j]=i;
DFS(x+1);
edge2[i]=0;edge2[j]=0;
}
}
break;
}
}
}
void solve(){
int i;
sort(node+1,node+n+1,cmp);
for(i=2;i<=n;i++){
if(node[i-1].y==node[i].y){
edge1[i-1]=i;
}
}
DFS(1);
printf("%d\n",ans);
}
int main(){
// clock_t t1=clock();
freopen("wormhole.in","r",stdin);
freopen("wormhole.out","w",stdout);
scanf("%d",&n);
int i;
for(i=1;i<=n;i++){
scanf("%d%d",&node[i].x,&node[i].y);
node[i].k=i;
}
solve();
// clock_t t2=clock();
// printf("%lf\n",(double)(t2-t1)/CLOCKS_PER_SEC);
return 0;
}