這是一道歐拉回路的板子題,惟一的不一樣在於要輸出是怎麼在那幾個環上轉出的答案,這樣就不能用鄰接矩陣存圖(其實本題的數據也直接否認了鄰接矩陣存圖的方法)node
不斷的在尋找一個簡單環,並在它上轉一次,至關於消掉一個環,並把全部路徑記錄在一個 stack 之中,在 stack 中必定會造成 這樣一種路徑 a.....a b......b c.......c由於最後必定會轉回起點,因此能夠倒序輸出一個被同一終點起點包圍的點c++
#include<bits/stdc++.h> using namespace std; int n,m; struct node{ int to,nxt; }e[2000010];int tot; int first[2000010]; int ind[2000010]; stack<int>sta; queue<int>q; int ans; inline void add_edge(int a,int b){ e[++tot].to=b,e[tot].nxt=first[a],first[a]=tot; e[++tot].to=a,e[tot].nxt=first[b],first[b]=tot; } inline int kd(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();} return x*f; } void dfsl(int x,int root){ ind[x]-=2;//由於正反兩邊都不能走了因此入度會減二 for(int i=first[x];i;i=e[i].nxt){ int to=e[i].to; if(e[i].to==0)continue; else{ e[i].to=e[((i-1)^1)+1].to=0; //正反兩邊都不能再走了,就破壞掉 if(to==root){ sta.push(to),sta.push(x); return; } dfsl(to,root); sta.push(x); return; } } } int main(){ n=kd(),m=kd(); for(int i=1;i<=m;i++){ int a=kd(),b=kd(),c=kd(),d=kd(); if(c==d)continue;//只有在不一樣時纔有走這條邊的必要 else{ add_edge(a,b); ind[a]++,ind[b]++;//添加邊和增長入度 } } for(int i=1;i<=n;i++){ if(ind[i]&1){//若是有奇數入度的邊必定是不會有歐拉回路的 cout<<"NIE"<<endl; return 0; } } for(int i=1;i<=n;i++){ if(ind[i]){ while(ind[i]){ dfsl(i,i); ans++; } } } printf("%d\n",ans); int root; while(sta.empty()==false){ int now; now=sta.top(); sta.pop(); q.push(now); if(q.size()==1){//若是這是一個開始 root=q.front(); } else if(now==root){//若是陷入輪迴,這是一個結束 cout<<q.size()-1<<" "<<now<<" ";q.pop(); while(q.empty()==false)cout<<q.front()<<" ",q.pop();//循環輸出在隊列裏保存好的路徑 puts(""); } } return 0; }