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;
}

你可能感兴趣的:(poj)