無向圖求尤拉路徑,迴路 模板(Hierholzer 演算法)
阿新 • • 發佈:2019-01-26
定義:
歐拉回路:每條邊恰好只走一次,並能回到出發點的路徑
尤拉路徑:經過每一條邊一次,但是不要求回到起始點
歐拉回路存在性的判定:
無向圖
每個頂點的度數都是偶數,則存在歐拉回路。
有向圖
每個節頂點的入度都等於出度,則存在歐拉回路。
尤拉路徑存在性的判定:
有向圖 : 圖連通,當且僅當該圖所有頂點數的度數為0,或者一個頂點的度數為1,另一個頂點的度數為-1,其他頂點的度數為0。
無向圖:圖連通,當且僅當該圖所有頂點的度數為偶數,或者除了兩個度數為奇數外其餘的全是偶數。
混合圖(有的邊是單向的,有的邊是無向的。常被用於比喻城市裡的交通網路有的路是單行道,有的路是雙行道):
找到一個給每條無向的邊定向的策略,使得每個頂點的入度等於出度,這樣就能轉換成上面第二種情況。
const int MAXN = 1005; int G[MAXN][MAXN];//存圖 int cnt[MAXN];//存每個點度的奇偶性 int N,M;//點個數,邊條數 stack<int> S;//存路徑 void dfs(int u){ for(int v=1; v<=N; v++) if(G[u][v]){ G[u][v]-=1; G[v][u]-=1; dfs(v); //不用恢復邊! } S.push(u);//出棧時記錄 } inline void Print(){//輸出路徑 if(!S.empty()){ printf("%d",S.top()); S.pop(); } while(!S.empty()){ printf(" %d",S.top()); S.pop(); } printf("\n"); } inline void init(){ memset(cnt,0,sizeof cnt); memset(G,0,sizeof G); } int main(){ while(scanf("%d %d",&N,&M) == 2){ init(); int u,v; for(int i=1 ; i<=M ; ++i){ scanf("%d %d",&u,&v); G[u][v] += 1; G[v][u] += 1; cnt[u] ^= 1;//利用了異或運算,0表示度為偶數,1表示度為奇數。 cnt[v] ^= 1; } for(u=1; u<=N ; ++u){//注意判斷圖是否從1點開始 if(cnt[u]) break; } if(u == N+1) dfs(1);//都為偶節點,從隨便一個開始都行 else dfs(u);//從奇節點開始 Print(); } return 0; }