先判定是否为欧拉图,俩个条件,不说了。如果是欧拉图,输出路经。
方法: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\n");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 +\n",ans[i][0]);
else
printf("%d -\n",ans[i][1]);
}
}
else
printf("No solution\n");
}