Problem surface
Title Solution
First of all, there is an obvious conclusion that the edges that do not need to be modified can be deleted directly, and the edges that need to be modified can be reserved. The white dot is that the number of times each edge is to be visited can be directly modeled as two. If an edge is proved to be connected with two blocks on both sides by two times, then if the two times are deleted, the two sides can be divided into one Euler circuit without affecting the answer.
So the rest of the edges are directly calculated as Euler loops for each connected block.
Then we can find all the simple rings directly (dfs \) for the graph after forced orientation.
#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; }