链接
http://acm.hdu.edu.cn/showproblem.php?pid=6311
题解
无向图度为奇数的点肯定有偶数个(因为所有点的度之和为偶数)
那么把这偶数个点两个一组,每组的两个点之间连一条边,形成的图每个分量都是欧拉图
每个分量求出欧拉回路,然后从我加的边的地方断成若干条环就是答案了
代码
#include <bits/stdc++.h>
#define maxn 100010
#define maxe 400010
#define iinf 0x3f3f3f3f
using namespace std;
struct Graph
{
int etot, head[maxn], to[maxe], next[maxe], w[maxe];
void clear(int N)
{
for(int i=1;i<=N;i++)head[i]=0;
etot=1;
}
void adde(int a, int b, int c){to[++etot]=b;w[etot]=c;next[etot]=head[a];head[a]=etot;}
}G;
vector<int> ans;
bool vis[maxe];
int deg[maxn];
void dfs(Graph &G, deque<int> &lis, int pos)
{
for(auto p=G.head[pos];p;p=G.next[p])
if(!vis[p])
{
vis[p]=vis[p^1]=1;
dfs(G,lis,G.to[p]);
if(p&1)lis.emplace_front(-p/2);
else lis.emplace_front(p/2);
}
}
int main()
{
int n, m, u, v, i, cnt;
ios::sync_with_stdio(false);
while(cin>>n>>m)
{
G.clear(n);
for(i=1;i<=n;i++)deg[i]=0;
for(i=1;i<=m;i++)
{
cin>>u>>v;
G.adde(u,v,0);
G.adde(v,u,0);
deg[u]++, deg[v]++;
}
vector<int> v;
for(i=1;i<=n;i++)if(deg[i]&1)v.emplace_back(i);
while(!v.empty())
{
auto x=v.back(); v.pop_back();
auto y=v.back(); v.pop_back();
G.adde(x,y,0);
G.adde(y,x,0);
}
for(i=1;i<=G.etot;i++)vis[i]=0;
deque<int> lis;
cnt=0;
ans.clear();
for(i=1;i<=n;i++)
{
lis.clear();
dfs(G,lis,i);
if(lis.empty())continue;
bool flag=false;
for(auto e:lis)if(abs(e)>m)flag=true;
if(flag)
{
while(abs(lis.front())<=m)lis.emplace_back(lis.front()), lis.pop_front();
lis.emplace_back(lis.front()), lis.pop_front();
for(auto e:lis)
{
if(abs(e)<=m)ans.emplace_back(e);
else cnt++, ans.emplace_back(iinf);
}
}
else
{
cnt++;
for(auto e:lis)ans.emplace_back(e);
ans.emplace_back(iinf);
}
}
cout<<cnt<<'\n';
v.clear();
for(auto e:ans)
{
if(e!=iinf)v.emplace_back(e);
else
{
cout<<v.size();
for(auto x:v)cout<<' '<<x;
cout<<'\n';
v.clear();
}
}
}
return 0;
}