Original title: http://acm.hdu.edu.cn/showproblem.php?pid=6311
For a graph (not necessarily connected), at least how many strokes (paths) are needed to cover all edges and output paths.
Euler Road, for a connected graph, needs max (1, odd points / 2) pen to finish.
In this problem, for each connecting block, press "pair" to add edges to the points with odd degrees (only two points are left as the starting point and the ending point, which should be understood in this way). The added edge is the "virtual" edge.
After completing the diagram, run a dfs and add the edge to the set to find the path of Euler road.
During statistics, when encountering real edge, res + +, the path is added to the answer continuously. Until the virtual edge is encountered (it should be understood that it can't be finished in this stroke, so we need to start another stroke).
#include <bits/stdc++.h>
using namespace std;
int n,m;
int e = 0;
struct Edge{
int u;
int v;
int id;
bool vis;
int next;
};
Edge edge[400005];
int head[100005];
int du[100005];
void addedge(int u,int v,int id) {
edge[e].u = u;
edge[e].v = v;
edge[e].id = id;
edge[e].vis = false;
edge[e].next = head[u];
head[u] = e++;
}
bool vis[100005];
vector<int> ji;
void dfs1(int u) {
vis[u] = true;
if(du[u] & 1) ji.push_back(u);
for(int i = head[u]; i != -1; i = edge[i].next) {
int to = edge[i].v;
if(vis[to]) continue;
dfs1(to);
}
}
vector<int> ac;
void dfs2(int u) {
for(int i = head[u]; i != -1; i = edge[i].next) {
if(edge[i].vis) continue;
edge[i].vis = true;
edge[i ^ 1].vis = true;
dfs2(edge[i].v);
ac.push_back(edge[i].id);
}
}
vector<int> ans[100005];
int res;
int main() {
while(scanf("%d%d",&n,&m) != EOF) {
e = 0;
for(int i = 0; i <= n; i++) {
head[i] = -1;
vis[i] = false;
du[i] = 0;
ans[i].clear();
}
res = 0;
int u,v;
int id = 1;
for(int i = 1; i <= m; i++) {
scanf("%d%d",&u,&v);
addedge(u,v,id);
addedge(v,u,-id);
id++;
du[u]++;
du[v]++;
}
for(int i = 1; i <= n; i++) {
// Orphans and points that have been visited skip
if(vis[i] || du[i] == 0) continue;
// Find a connection block in dfs1, and find the point with odd degree
ji.clear();
dfs1(i);
// For a connected block, if there is no point with odd degree
// Then you can run Euler road from any point, otherwise you should start from the point with odd degree
int st = ji.empty() ? i : ji[0];
// Leave a pair of points, which should be the starting point and the ending point
// If the degree of a connected graph is odd, it should be even
for(int j = 2; j < ji.size(); j += 2) {
addedge(ji[j],ji[j + 1],0);
addedge(ji[j + 1],ji[j],0);
}
// dfs2, the Euler path of a complemented graph
ac.clear();
dfs2(st);
for(int j = ac.size() - 1; j >= 0; j--) {
// Virtual edge skip
if(ac[j] == 0) continue;
// Real edge, res++
res++;
// If it's all real, you can draw with one stroke
while(ac[j] != 0 && j >= 0) {
ans[res].push_back(ac[j]);
j--;
}
}
}
// output
printf("%d\n",res);
for(int i = 1; i <= res; i++) {
printf("%d",ans[i].size());
for(int j = 0; j < ans[i].size(); j++) {
printf(" %d",ans[i][j]);
}
printf("\n");
}
}
return 0;
}