标签:
一笔画问题
zyc从小就比较喜欢玩一些小游戏,其中就包括画一笔画,他想请你帮他写一个程序,判断一个图是否能够用一笔画下来。
规定,所有的边都只能画一次,不能重复画。
2 4 3 1 2 1 3 1 4 4 5 1 2 2 3 1 3 1 4 3 4
No Yes
一笔画问题是一个运用搜索和欧拉回路才能做出来的题目,如果光用搜索能 做出来,但是会远远的超时,所以不能单单使用搜索来做,其实搜索很多题目都是 要通过剪枝来避免超时的,欧拉回路就是专门解决一笔画问题的。如果不知道什 么是欧拉回路可以看一看欧拉回路的具体定义,这里简单说一下欧拉回路,在一个 无向图中,如果无向图是连通的,如果有两个奇点(被奇数个线来接着的点),则 必须从其中一个奇点出发,另一个奇点终止;如果奇点不存在或有一个奇点,则可 以从任意点出发,最终一定能走完所以结点,称为欧拉回路。用欧拉回路进行判断 可以减去很多无用功,避免超时。
【代码】
#include<stdio.h> #include<string.h> #define INF 0x3f3f3f3f int e[1010][1010],Q,P,flag; void dfs(int cur,int s) { if(flag==1) return ; int i; if(s==Q) { flag=1; printf("Yes\n"); return; } for(i=1;i<=P;i++) { if(e[cur][i]==1) { e[cur][i]=0; e[i][cur]=0; dfs(i,s+1); e[cur][i]=1; e[i][cur]=1; } } return ; } int main() { int N,x; scanf("%d",&N); while(N--) { int arr[1010]={0},tmp; flag=0,x=0; scanf("%d %d",&P,&Q); int i,j,a,b; memset(e,0,sizeof(e)); for(i=1;i<=P;i++) for(j=1;j<=P;j++) if(i==j) e[i][j]=0; else e[i][j]=INF; for(i=1;i<=Q;i++) { scanf("%d %d",&a,&b); arr[a]++; // 新定义一个数组用来储存输入的数,出来的次数 arr[b]++; e[a][b]=1; e[b][a]=1; } for(i=1;i<1010;i++) { if(arr[i]%2==1) // 求出有多少个奇点(一个点由奇数个线连接) { tmp=i; x++; } } if(x>2) // 如果出来奇数的个数大于2个说明没有结果,他们只有一个入口没有出口,所以超过2个肯定画不完 { printf("No\n"); continue; } if(x==2||x==1) dfs(tmp,0); // 如果有2个或1个出现一次的,只可能从一个开始从另一个结束,不然不可能画完 else dfs(1,0); // 如果都是出现次数大于1,就相当于一个环,从哪开始都一样 if(flag==0) printf("No\n"); } return 0; }
标签:
原文地址:http://blog.csdn.net/disparity_cjk/article/details/51331481