传送门:http://codeforces.com/contest/723/problem/E
好久没写博客了,越来越懒,也越来越菜,最近学了些新知识,准备重新调整好学习的状态。
Fleury其实就是相当于DFS,但是跟纯DFS不同,因为直接DFS的话,在某些情况下,可能会走进死路,这时候就要拿一个栈来记录路径,如果当前情况下不能扩展,就把当前这个节点输出,能扩展的话,就DFS进去,把途中的节点入栈。最后输出出来的欧拉路径其实是倒着的。
这里有一个我自己想的例子,如果直接DFS,是有可能DFS进死路,导致无法找出正确答案的。
比如这个图,如果直接1->2->3->4->1->3,就出不来了。
1->2->3->4->6->5->2->4->1->3这是一个能走完边的路径。
再讲到这题上,因为这题我是看了别人的博客的,有一个思路非常的强,就是创建一个n+1节点,把所有奇数度数节点都连到n+1上去,这样修改后的图,保证能产生欧拉回路。因为每添加一条边,图里的总度数+2,所以奇数度数的点的个数一定是偶数个,那么连了边以后,n+1那个节点的度数一定是偶数,所以每个点的度数都是偶数,因此一定会产生欧拉回路。但是因为图不一定连通,导致会产生好几个连通分量,所以要从每个点出发Fleury一次,才可以求出所有边。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <ctime>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define pb push_back
#define mp make_pair
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define calm (l+r)>>1
const int INF = 2139062143;
const int maxn=220;
int n,m;
struct EE{
int to,next,v;
}edge[maxn*maxn];
int head[maxn],Ecnt,deg[maxn];
vector<int> st;
inline void add(int a,int b){
edge[Ecnt].to=b;
edge[Ecnt].next=head[a];
edge[Ecnt].v=1;
head[a]=Ecnt++;
}
vector<int> ans;
void dfs(int x){
st.pb(x);
for(int &i=head[x];~i;i=edge[i].next){
if(!edge[i].v)continue;
edge[i].v=edge[i^1].v=0;
dfs(edge[i].to);
return;
}
}
void Fleury(int x){
st.clear();
ans.clear();
st.pb(x);
while(!st.empty()){
bool has=false;
int s=st.back();st.pop_back();
for(int i=head[s];~i;i=edge[i].next){
if(edge[i].v){
has=true;break;
}
}
if(!has){
ans.pb(s);
}
else{
dfs(s);
}
}
}
int main(){
//freopen("D://input.txt","r",stdin);
int T;scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
memset(head,-1,sizeof head);
memset(deg,0,sizeof deg);
Ecnt=0;
for(int i=1;i<=m;i++){
int a,b;scanf("%d%d",&a,&b);
add(a,b);add(b,a);
deg[a]++;deg[b]++;
}
int cnt=0;
for(int i=1;i<=n;i++){
if(deg[i]%2){
cnt++;
add(i,n+1);add(n+1,i);
}
}
printf("%d\n",n-cnt);
for(int i=1;i<=n;i++){
Fleury(i);
if(ans.size()>1){
for(int j=ans.size()-1;j>=1;j--){
if(ans[j]!=n+1&&ans[j-1]!=n+1)printf("%d %d\n",ans[j],ans[j-1]);
}
}
}
}
return 0;
}