Problem Description
欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?
Input
测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是节点数N ( 1 < N < 1000 )和边数M;随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号(节点从1到N编号)。当N为0时输入结
束。
束。
Output
每个测试用例的输出占一行,若欧拉回路存在则输出1,否则输出0。
Sample Input
3 3 1 2 1 3 2 3 3 2 1 2 2 3 0
Sample Output
1 0解题报告:具体dfs,bfs可详见http://blog.youkuaiyun.com/scarlett_geng/article/details/47397521这个题是我学习搜索之后写的第一个dfs的问题,用了将近两个半天的时间调的吧,自己完整的敲了三遍,出的问题比较多,还有代码风格注释的问题,学的东西也算是比较多的所以想写一下。这个题了解了dfs和欧拉回路的概念之后,并不是很难,首先这个题肯定是一个无向图,而判断无向图是否有欧拉回路,有两个判断条件,一个是是否是连通图(可以用并查集和普通方法判断,这里先用普通方法),即从第一个点开始遍历,每遍历一个点ans++,结束后判断ans是否等于全部的点n,如果等于,即是连通的。第二个条件是判断是否每个点的度数都为偶数。这个一定要特别注意,一开始5210和我都sb了,没有想到一个点可能有多条边,直接写成了读到一个点后mp[i][j]=1,mp[j][i]=1,然后到了判断度的时候就直接degree++,所以这是一个问题,竟然一直没有先到(这里还是想吐槽一下看来我还是不太适合去当测试员,一般特殊情况很难想到orz)。所以这里应该是mp[i][j]++,mp[j][i]++,degree+=mp[i][j]。然后有向图的判断就是是不是联通的,入度是否等于出度。在dfs里面写的时候最初的时候忘记了ans++,每次判断一次ans都要++,这样最后才可以==n。输出的时候记得第二个情况不符合条件的话也要输出的,而我第一次没有写= =。最后要注意一下输入的格式处理,第一个如果为0,就直接退出了,所以不能直接输入两个,要输入第一个就判断,这是while(1)的用法。。总的来说。。注意的地方还是很多的。。革命仍在继续。。以后仍需努力。。上一下千疮百孔的代码。。#include<cstdio> #include<cstring> using namespace std; #define MAXN 1000+10 int m,n,mp[MAXN][MAXN],vis[MAXN];//全局变量默认就为0,所以这里不用设初始值为0 int ans; //ans因为两个函数都要用到,所以设成全局变量 //dfs void dfs(int u) { vis[u]=1; for(int i=1;i<=n;i++) { if(vis[i]==0&&mp[u][i]) { dfs(i); //这个时候已经遍历了第一个点了,所以不能直接ans++了,要先dfs,再自增 ans++; } } } //判断是否连通 int judge() //只要从第一个点开始遍历,遍历到n个点就可以,不用加循环每个都遍历了 { ans=1; if(!vis[1]) dfs(1); if(ans==n) return 1; else return 0; } int main() { int a,b,degree,flag=0; //虽然是看似是两个数据的输入, //但是如果n==0的话,就直接停止了,所以不可以两个一起输入, //要先判断第一个输入的不为0的时候,再输入第二个数 while(1) { scanf("%d",&n); if(n==0) break; scanf("%d",&m); memset(vis,0,sizeof(vis)); //每个要用到的数据一定要初始化,这个总是容易忽略 memset(mp,0,sizeof(mp)); flag=0; int c=0; for(int i =0;i<m;i++) { scanf("%d %d",&a,&b); mp[a][b]++; //这里一开始写的是mp[][]=1,因为以为一个点只可以连接一条边,是个bug。可以一个点连多个边的 mp[b][a]++; } for(int i = 1;i<=n;i++) //这里i=1,j=2 和i=2,j=1是不一样的, //因为是要算每个结点的度数,所以每个点都要遍历所有的和它相连的边 { degree=0; for(int j= 1;j<=n;j++) //内循环不能写成i+1 { if(mp[i][j]) //这里和上面一样,只要不是0就行 degree+=mp[i][j]; //degree就不是自增了,要加上所有边的值 } if(degree%2!=0) { flag=1; break; } } //printf("%d",flag); if(flag==1) { printf("0\n"); //这里不要写break,否则就所有跳出了。要用continue直接输入下一组数据 continue; //这个地方wa了两次,然后测数据的时候发现当flag==1的时候不输出结果,后来让它输出中间变量之后才发现这里先要printf,再continue } c= judge(); if(c==1&&flag==0) printf("1\n"); else printf("0\n"); //不可以这一步不要了 ,因为也可能是第二个条件不满足 } return 0; }