LOJios
首先有一個比較顯然的結論,對於不須要修改顏色的邊能夠直接刪掉,對於須要修改的邊保留。說白點就是每條邊要被訪問的次數能夠直接模二。證實的話就是若是一條邊被通過了兩次,證實其連通了兩側的兩個塊,那麼把這兩次刪掉,能夠把兩側各拆分紅一個歐拉回路,不會影響答案。
因而剩下的邊直接對於每個連通塊算歐拉回路。
而後對於強制定向以後的圖直接\(dfs\)找到全部簡單環就能夠了。spa
#include<iostream> #include<cstdio> #include<vector> using namespace std; #define MAX 100100 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } int n,m; int f[MAX]; int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);} struct Line{int v,next;}e[MAX*20]; int h[MAX],cnt=2,dg[MAX],cur[MAX]; void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;dg[v]++;} bool vis[MAX*10];int dir[MAX*10]; vector<int> Ans[MAX];int tot; void dfs(int u) { for(int &i=cur[u];i;i=e[i].next) { if(vis[i>>1])continue;int j=i; vis[i>>1]=true;dfs(e[i].v); dir[j>>1]=j&1; } } int St[MAX],top;bool inq[MAX]; void DFS(int u) { St[++top]=u;inq[u]=true; for(int &i=h[u];i;i=e[i].next) { if(!inq[u])return; int v=e[i].v;if((i&1)!=dir[i>>1])continue; if(inq[v]) { int p;++tot;Ans[tot].push_back(v); do{p=St[top--];Ans[tot].push_back(p);inq[p]=false;}while(p!=v); St[++top]=v;inq[v]=true; } else DFS(v); } } int main() { n=read();m=read(); for(int i=1;i<=n;++i)f[i]=i; for(int i=1;i<=m;++i) { int u=read(),v=read(),s=read(),t=read(); if(s^t)Add(u,v),Add(v,u),f[getf(u)]=getf(v); } for(int i=1;i<=n;++i)if(dg[i]&1){puts("NIE");return 0;} for(int i=1;i<=n;++i)cur[i]=h[i]; for(int i=1;i<=n;++i)if(getf(i)==i)dfs(i); for(int i=1;i<=n;++i)DFS(i); printf("%d\n",tot); for(int i=1;i<=tot;++i) { printf("%d ",(int)Ans[i].size()-1); for(int u:Ans[i])printf("%d ",u);puts(""); } return 0; }