一笔画问题(euler-circuit.cpp)
题目描述对给定的一个无向图,判断能否一笔画出。若能,输出一笔画的先后顺序,否则输出“No Solution!”
所谓一笔画出,即每条边仅走一次,每个顶点可以多次经过。
输出字典序最小的一笔画顺序。
输入
第1行:1个整数n,表示图的顶点数(n<=100)
接下来n行,每行n个数,表示图的邻接矩阵
输出
第1行:一笔画的先后顺序,每个顶点之间用一个空格分开
样例输入
样例一
3
0 1 1
1 0 1
1 1 0
样例二:
7
0 1 0 1 1 0 1
1 0 1 0 0 0 0
0 1 0 1 0 0 0
1 0 1 0 0 0 0
1 0 0 0 0 1 0
0 0 0 0 1 0 1
1 0 0 0 0 1 0
样例输出
样例一:
1 2 3 1
样例二:
1 2 3 4 1 5 6 7 1
#------------------------------------------------------------------------------#
此题说难也不难,输入的地方它已简化,直接存在邻接矩阵即可。
注意要统计一下每个点的度(即看一下这个点是奇数点还是偶数点)不懂一笔画……点击一下,如果奇数点大于2个肯定是不行的,直接“No Solution!”,否则就从其中一个出发,没有的话就从偶数点开始,注意要字典序最小。
递归就一个参数——当前到哪个点了,然后从1循环到当前,如果可以到就进入,注意此时要将此路封闭,出来时存一下就可以了。
代码:
#include<cstdio> int a[105][105],ans[10005],p; int n,f,b=1,al; void m(int x) { for(int i=1;i<=n;i++) if(a[x][i]==1) { a[x][i]=0; a[i][x]=0;//x点到i点和i点到x点都要清0,以免重复递归 m(i); } ans[++al]=x;//记录路径 } int main() { freopen("euler-circuit.in","r",stdin); freopen("euler-circuit.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) { p=0;//存当前点的度 for(int j=1;j<=n;j++) { scanf("%d",&a[i][j]); if(a[i][j]==1) p++;//如果有联通,度++ } if(p%2==1)//度为奇数(奇数点) { if(f==0)//f用来看是否为第一个奇数点,顺便统计有多少个奇数点 b=i;//b是存开始点 f++; } } if(f>2)//奇数点大于2便一定无法完成 { printf("No Solution!"); return 0; } m(b);//开始递归 printf("%d",ans[al]); for(int i=al-1;i>=1;i--) printf(" %d",ans[i]); return 0; }
By WZY