1. 程式人生 > 實用技巧 >「學習筆記」尤拉路

「學習筆記」尤拉路

Description

尤拉路:圖中經過所有邊恰好一次的路徑

歐拉回路:起點和終點相同的尤拉路

判定

分為有向圖和無向圖兩種情況:

\(1.\) 無向圖

\((1)\) 所有點的度數都是偶數,此時起點任選兩個即可

\((2)\) 恰好有兩個點的度數是奇數,此時兩個奇度數點為起點或終點

\(2.\) 有向圖

\((1)\) 所有點的入度都等於出度,此時存在歐拉回路,所有點都可以做起點

\((2)\) 有兩個點入度不等於出度,同時滿足兩個點有一個入度大於出度,有一個入度小於出度,此時出度大的是起點,入度大的是終點

Hierholzer演算法

(挺簡單的)

暴力演算法就是對於當前到的點,列舉所有的出邊

然後如果沒訪問過就搜過去

複雜度 \(O(nm)\)

然後發現缺陷在於每次都從頭開始,這並不優秀,加上一個類似 \(dinic\) 當前弧優化的東西就行了

inline void dfs(int x)
{
    for(int i=head[x];i;i=e[i].nxt)
    {
        if(vis[i]) continue;
        int t=e[i].to; vis[i]=vis[i^1]=1;
        head[x]=i; dfs(t); i=head[x];
    }
    return st[++top]=x,void();
}

複雜度 \(O(n+m)\)


\(Rorschach-XR\) 的部落格裡面寫這種東西遞迴太慢了?

int x,r[N*10],i,cnt,top,st[N*10];
inline void find()
{
    st[++top]=1; 
    while(top)
    {
        int x=st[top],i=head[x]; 
        while(vis[i]) i=e[i].nxt;
        if(i) 
        {
            int t=e[i].to;
            vis[i]=vis[i^1]=1; 
            head[x]=i;
        }
        else top--,r[++cnt]=x;
    }
    return ;
}

答案就是棧內元素的倒序

其實找尤拉路可能見的少,但是有尤拉路的相關性質倒是很常用

比如:星際旅行

每條邊拆開之後做無向聯通圖