先判定是否为欧拉图,俩个条件,不说了。如果是欧拉图,输出路经。
方法:dfs遍历边,回溯时候记录边,遍历过了就标记“双向边”.
那么所记录的恰好是一条逆欧拉迹。不可以前进的时候标记,原因:有可能一笔画失败,导致边不连续,而回溯的时候记录,原因较复杂,大致证明如下:
分几种情况讨论即可:
1,只有偶数结点。任选一个点,必然从一条出发回到该点,直到无边为止,回溯时边自然连续。
2,有2个奇数结点。当回到某个点时无论圈有没走,必然也连续,见图:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n;int nume=0; int e[205][2];int head[10]; void adde(int f,int l) { e[nume][0]=l;e[nume][1]=head[f];head[f]=nume++; e[nume][0]=f;e[nume][1]=head[l];head[l]=nume++; } int degree[8]; //度数 int vis[205]; //标记访问 void dfs1(int u) //判断连通 { for(int i=head[u];i!=-1;i=e[i][1]) { int v=e[i][0]; if(!vis[v]) { vis[v]=1; dfs1(v); } } } int ans[205][2];int ansnum=0; void dfs2(int u) //求欧拉迹 { for(int i=head[u];i!=-1;i=e[i][1]) { if(!vis[i]) { vis[i]=1; //此处同时标记双向边!!!。 vis[i^1]=1; int v=e[i][0]; dfs2(v); //回溯的时候记录边,恰是一条欧拉路。 if(i%2==0) ans[ansnum++][0]=i/2+1; else ans[ansnum++][1]=i/2+1; } } } int main() { scanf("%d",&n); for(int i=0;i<8;i++) head[i]=-1; int tf,tl; int tbegin=0; for(int i=0;i<n;i++) { scanf("%d%d",&tf,&tl); tbegin=tf; degree[tf]++;degree[tl]++; adde(tf,tl); } int count=0; int jis=0;; for(int i=0;i<=6;i++) //度数判定 { if(degree[i]%2) { count++; jis=i; } } if(count==0||count==2) { int mark=1; vis[tbegin]=1; dfs1(tbegin); for(int i=0;i<=6;i++) //连通性判定 if(vis[i]==0&°ree[i]>0) mark=0; if(mark==0){ printf("No solution ");return 0;} for(int i=0;i<205;i++) vis[i]=0; if(count==0) dfs2(tbegin); else dfs2(jis); for(int i=ansnum-1;i>=0;i--) //逆序输出 { if(ans[i][0]!=0) printf("%d + ",ans[i][0]); else printf("%d - ",ans[i][1]); } } else printf("No solution "); }