[欧拉回路] 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;
}

浙公网安备 33010602011771号