[欧拉回路] CF723E One-Way Reform

posted on 2024-04-08 06:23:18 | under | source

称度数为偶数的点为偶数点,反之为奇数点。

首先答案上界必定是偶数点数量。

尝试构造到上界。由于欧拉回路上的点必定入度 \(=\) 出度,所以如果构造出一个欧拉回路图,那么就能卡到上界了。

有个结论:无向图奇数点数量必定为偶数。证明也很简单,总度数为偶数嘛。

所以让奇数点两两相连即可,为了省事可以让它们统一连向一个虚点。这也是欧拉路一类问题的常用套路了。

然后在新图上跑欧拉回路,跟着回路来定向,如果是原来的边就输出即可。

代码

#include<bits/stdc++.h>
using namespace std;

const int N = 2e2 + 5;
int T, n, m, ans, ct[N][N], u, v;
bool was[N];
vector<int> to[N];

inline void add(int u, int v) {to[u].push_back(v), ++ct[u][v];}
inline void dfs(int u){
	was[u] = 1;
	for(auto v : to[u]){
		if(!ct[u][v]) continue;
		--ct[u][v], --ct[v][u];
		if(u && v) printf("%d %d\n", u, v);
		dfs(v);
 	}
}
inline void calc(){
	memset(ct, 0, sizeof ct);
	for(int i = 0; i < N; ++i) was[i] = 0, to[i].clear();
	cin >> n >> m, ans = n;
	for(int i = 1; i <= m; ++i) 
		scanf("%d%d", &u, &v), add(u, v), add(v, u);
	for(int i = 1; i <= n; ++i)
		if(to[i].size() & 1) --ans, add(0, i), add(i, 0);
	printf("%d\n", ans);
	for(int i = 1; i <= n; ++i) if(!was[i]) dfs(i);
}
int main(){
	cin >> T;
	while(T--) calc();
	return 0;
}
posted @ 2026-01-13 11:16  Zwi  阅读(0)  评论(0)    收藏  举报