首先考虑是欧拉图。若从一个顶点出发,利用DFS,将新搜索到的顶点保存到栈顶,并且将走过的边给删除,那么一定能访问到这个初始顶点。因为除起始顶点外其他的顶点若被访问到那么一定能去访问别的顶点。但是起始顶点不同,它是被直接访问的,即没有通过别的顶点去访问它,因此我们一定能找到这样的回路,使得起始顶点和终点是同一顶点,设为v,并且v的所有边都在这条回路上。我们用栈来保存这些顶点(按访问的顺序),如果此时栈顶的元素的所有边都被访问过,我们就输出这个顶点并从栈顶释放出这个顶点,紧接着我们对现在栈顶上的元素进行重复操不断的进行DFS,并且也一定能找到上文提到的WT回路。现在不难看出Euler回路实际上是有多个回路所构成的,并且这些回路都是独立的,即没有边的交集,所以基于上述事实,我给出了一个新算法。
Note:copyright from Avenger
#include<iostream>
using namespace std;
int A[100][100],n;
struct node
{
int top;
int nodes[100];
}f;
void DFS(int x)
{
int i;
f.top++;
f.nodes[f.top]=x;
for(i=1;i<=n;i++)
{
if(A[x][i])
{
A[x][i]--;
A[i][x]--;
DFS(i);
break;
}
}
}
void Euler(int x)
{
f.top=1;
f.nodes[f.top]=x;
while(f.top)
{
int b=0;
for(int i=1;i<=n;i++)
{
if(A[f.nodes [f.top] ] [i] )
b=1;
}
if(!b)
{
cout<<f.nodes[f.top]<<" ";
f.top--;
}
else
{
f.top--;
DFS(f.nodes[f.top+1]);
}
}
}
int main()
{
int m,s,t,start=1,count=0;
cin>>n>>m;
memset(A,0,sizeof(A));
for(int i=1;i<=m;i++)
{
cin>>s>>t;
A[s][t]++;
A[t][s]++;
}
for(int i=1;i<=n;i++)
{
int sum=0;
for(int j=1;j<=n;j++)
{
sum+=A[i][j];
}
if(sum%2==1)
{
count++;
start=i;
}
}
if(count==0||count==2)
Euler(start);
else
cout<<"There's no Euler path"<<endl;
return 0;
}
对于半欧拉图也是可行的。
Note:copyright from Avenger
#include<iostream>
using namespace std;
int A[100][100],n;
struct node
{
int top;
int nodes[100];
}f;
void DFS(int x)
{
int i;
f.top++;
f.nodes[f.top]=x;
for(i=1;i<=n;i++)
{
if(A[x][i])
{
A[x][i]--;
A[i][x]--;
DFS(i);
break;
}
}
}
void Euler(int x)
{
f.top=1;
f.nodes[f.top]=x;
while(f.top)
{
int b=0;
for(int i=1;i<=n;i++)
{
if(A[f.nodes [f.top] ] [i] )
b=1;
}
if(!b)
{
cout<<f.nodes[f.top]<<" ";
f.top--;
}
else
{
f.top--;
DFS(f.nodes[f.top+1]);
}
}
}
int main()
{
int m,s,t,start=1,count=0;
cin>>n>>m;
memset(A,0,sizeof(A));
for(int i=1;i<=m;i++)
{
cin>>s>>t;
A[s][t]++;
A[t][s]++;
}
for(int i=1;i<=n;i++)
{
int sum=0;
for(int j=1;j<=n;j++)
{
sum+=A[i][j];
}
if(sum%2==1)
{
count++;
start=i;
}
}
if(count==0||count==2)
Euler(start);
else
cout<<"There's no Euler path"<<endl;
return 0;
}
对于半欧拉图也是可行的。