POJ 2230
//题目分类:有向图的欧拉路(利用深度优先搜索+邻接表)
//题目大意:一个图,要将每条边恰好遍历两遍,而且要以不同的方向,还要回到原点。
//定理:如果一个有向图所有顶点的入度等于出度,则该有向图存在欧拉回路。
//解题思路:此题实质是建立了一个双向连接的有向图。关键在于理解深搜时从S出发,为什么一定会回到S。可以从反证法角度考虑。
//假设遍历的顺序为S->A1->A2->A3->...->S->...->An,S在深搜过程中被遍历,则S的入度为1,出度为2,入度与出度不相等,与定理相违背。
//所以S一定是深搜的最后一个节点,这里注意理解深搜的最后一个节点的含义,是指S的临界表首先被遍历完,输出S。假设输出S的深搜的顺序是
//S->A1->A2->A3->...->Ai->S,输出S后回溯遍历S的上一个节点Ai,遍历Ai的邻接表,Ai->Ai+1->Ai+2->...->Ai,又由定理得存在欧拉路必须是节
//点的入度等于出度,所以下一次Ai的邻接表一定首先被遍历完,输出Ai。同理接着是回溯Ai的上一个节点Ai-1,最后回溯到S,输出S。欧拉路结束。
//这道题让我想了一下午,真得学会了不少东西,再次还用感谢这位牛人的博客http://gisyhy.blog.163.com/blog/static/12939034320102181045134/
#include <iostream>
//#include <conio.h>
#include <vector>
using namespace std;
#define arraysize 10001
typedef struct edge //边
{
int v;
bool flag;
};
vector<edge> grap[arraysize]; //存储邻接表
int n,m;
void DFS(int k)
{
int i,j;
for(i=0;i<grap[k].size();++i) //对第k个顶点的邻接表进行深搜
{
if(!grap[k][i].flag)
{
grap[k][i].flag = true;
DFS(grap[k][i].v);
}
}
cout<<k<<endl; //此处在回溯时进行输出
}
int main()
{
// freopen("1.txt","r",stdin);
int start,end;
int i,j;
edge temp;
while(cin>>n>>m)
{
for(i=0;i<m;++i)
{
cin>>start>>end;
temp.v = end;
temp.flag= false;
grap[start].push_back(temp);
temp.v = start;
temp.flag = false;
grap[end].push_back(temp);
}
DFS(1);
for(i=1;i<n+1;++i) //此处邻接表清空
grap[i].clear();
}
//getch();
return 0;
}