上面是摘自图论书上的定义。
算法在运行过程中删除了所有已走的路径,也就是说途中残留了所有没有行走的边。根据割边的定义,如果在搜索过程中遇到割边意味着当前的搜索路径需要改进,即提前输出某一个联通子集的访问序列,这样就能够保证访问完其中联通子图中后再通过割边访问后一个联通子图,最后再沿原路输出一开始到达该点的路径。如果只有割边可以扩展的话,只需要考虑先输出割边的另一部分联通子集访问序列。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1005;
struct node{
int v;
int able; //判断此边能不能走
int next;
}edge[N*2];
int head[N],cnt;
int Deg[N],//每个点的度数
s,//欧拉通路的起点,即度数为1的点
num;//奇度顶点的个数
int top,sta[N];//用来存放欧拉通路上的点
int n,m;
void init(){
s=1;
cnt=num=0;
memset(Deg,0,sizeof(Deg));
memset(head,-1,sizeof(head));
}
void add(int u,int v){
//printf("----%d\n",cnt);
edge[cnt].v=v;
edge[cnt].able=1;
edge[cnt].next=head[u];
head[u]=cnt++;
Deg[u]++;
}
void add_Edge(int u,int v){//无向图加双重边
add(u,v);
add(v,u);
}
int DFS(int x){ //寻找可以走的下一条路径
sta[top++]=x;
for(int i=head[x];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(edge[i].able){
edge[i].able=edge[i^1].able=0;//这条边变为不能走
DFS(v);
break;
}
}
}
void fleury(int ss){
int brige;
top=0;
sta[N];
sta[top++]=ss;
while(top>0){
brige=1;
int u=sta[top-1];
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].v;
if(edge[i].able){//判断与u相连的有没有没有被走过的
brige=0;
break;
}
}
if(brige) printf("%d ",sta[--top]); //是桥,则走到欧拉通路的终点
else DFS(sta[--top]);
}
}
int main(){
while(~scanf("%d%d",&n,&m)){
init();
for(int i=0;i<m;i++){
int u,v;
scanf("%d%d",&u,&v);
add_Edge(u,v);
}
for(int i=1;i<=n;i++)
if(Deg[i]&1){
num++;
s=i;
}
if(num==0||num==2){ //为0为欧拉回路,1为欧拉通路
printf("YES\n");
fleury(s);
}
else printf("NO\n");
}
return 0;
}