欧拉路径/欧拉回路

欧拉环:图中经过每条一次且仅一次的环;
欧拉路径:图中经过每条一次且仅一次的路径;
欧拉图:有至少一个欧拉环的图;
半欧拉图:没有欧拉环,但有至少一条欧拉路径的图。

欧拉路径和欧拉图的具体判断可 参考此处 


要特别注意的是,不要把欧拉路径和哈密顿路径搞混淆了,欧拉路径是每条边只经过一次的路径(而一个点可以经过多次),哈密顿路径是每个点只能经过一次的路径。哈密顿路径问题比欧拉路径问题要难的多。


不管是有向图还是无向图,欧拉回路都具有一个很明显的性质:对每个点有多少条边进去就一定要有多少条边出来。如果是欧拉路径,那么可以允许在路径的首位两端有少一个进去/出来的。

利用这个性质有以下算法求欧拉路径

即:选好起点后,把每走过的边在原图中删除。

如何选起点:1)如果所有的点都是入度==出度,任意起点都可以;2)否则,无向图:选其中一个度数为奇数的点;有向图:选出度比入度大1的点。

伪代码如下:

DFS(u):
	While (u存在未被删除的边e(u,v))
		删除边e(u,v)
		DFS(v)
	End
	PathSize ← PathSize + 1
	Path[ PathSize ] ← u

POJ2337,有向图的欧拉路径。

关键在于如何建图,并且要求字典序输出答案。

【代码&&模版】

/* ***********************************************
Author        :angon

************************************************ */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define showtime fprintf(stderr,"time = %.15f\n",clock() / (double)CLOCKS_PER_SEC)
#define lld %I64d
#define REP(i,k,n) for(int i=k;i'9'; ch=getchar());for(; ch>='0'&&ch<='9'; ch=getchar())s=s*10+ch-'0';return s;}

string s[N];
int out[26],in[26],vis[2005];
struct Edge
{
    int to,next;
    int idx;
}edge[2100];
int head[30],tot=0;
int num,path[N];
void addedge(int u,int v,int idx)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    edge[tot].idx = idx;
    head[u] = tot++;
}
void dfs(int u)
{
    for(int i =head[u]; ~i; i=edge[i].next)
    {
        if(vis[i]) continue;
        vis[i] = 1;
        dfs(edge[i].to);
        path[num++] = edge[i].idx;
    }

}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t; scan(t);
    while(t--)
    {
        int n; scan(n);
        REP(i,0,n)
            cin>>s[i];
        sort(s,s+n);
        mst(head,-1); tot=0;
        mst(out,0); mst(in,0); mst(vis,0);
        int start = 100;
        for(int i=n-1;i>=0;i--)
        {
            int u = s[i][0] - 'a';
            int v = s[i][s[i].length() - 1]- 'a';
            addedge(u,v,i);
            out[u]++;
            in[v]++;
            start = min(min(u,v),start);
        }
        bool flag = 0;
        int c1 = 0, c2 = 0;
        for(int i=0;i<26;i++)
        {
            if(out[i] - in[i] > 1 || in[i] - out[i] > 1)
            {
                flag = 1;
                break;
            }
            if(out[i] - in[i] == 1)
                c1++,start = i;
            if(out[i] - in[i] == -1)
                c2++;
        }
        if(flag || (c1+c2!=0 && c1+c2!=2))
        {
            puts("***");
            continue;
        }
        num = 0;
        dfs(start);
        if(num != n)
        {
            puts("***");
            continue;
        }
        for(int i=num-1;i>=0;i--)
        {
            cout<



你可能感兴趣的:(欧拉路径/欧拉回路)