CF527E Data Center Drama 题解
Solution
感觉联想到欧拉回路有点过于强大了。。。
给出一个不需要欧拉回路的算法。
问题转化为:保证所有点的入度和无向图上的度数都是偶数。
先去掉所有自环,默认把入度增加
(这里的
因此如果
容易发现,我们新增的边都是必要的。下面构造地证明解一定存在。
随便求出原图的一棵 DFS 树。
将非树边的指向随便定。
自底向上确定每条树边的方向。具体的,如果儿子的入度为奇数,树边就指向儿子,否则指向父亲。
而根节点的入度等于
因此我们找到了一个合法的方案。
#include<bits/stdc++.h>
#define ffor(i,a,b) for(int i=(a);i<=(b);i++)
#define roff(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int MAXN=1e5+10;
int n,m,deg[MAXN],dout[MAXN],vis[MAXN],dep[MAXN];
vector<int> G[MAXN],T[MAXN];
vector<pair<int,int>> ans;
void dfs(int u,int f) {
dep[u]=dep[f]+1,vis[u]=1;
int cnt=0;
for(auto v:G[u]) {
if(v==f) if(!cnt) {cnt=1;continue;}
if(vis[v]&&dep[v]<dep[u]) ans.push_back({u,v}),dout[u]++;
if(vis[v]) continue ;
T[u].push_back(v),dfs(v,u);
}
return ;
}
void solve(int u,int f) {
for(auto v:T[u]) {
solve(v,u);
if(dout[v]&1) ans.push_back({v,u});
else ans.push_back({u,v}),dout[u]++;
}
return ;
}
int main() {
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m;
ffor(i,1,m) {
int u,v;
cin>>u>>v;
if(u==v) {
ans.push_back({u,v}),dout[u]++;
continue ;
}
G[u].push_back(v),G[v].push_back(u),deg[u]++,deg[v]++;
}
vector<int> vc;
ffor(i,1,n) if(deg[i]&1) vc.push_back(i);
ffor(i,1,vc.size()/2) {
int u=vc[2*i-2],v=vc[2*i-1];
G[u].push_back(v),G[v].push_back(u);
m++;
}
if(m&1) m++,ans.push_back({1,1}),dout[1]++;
dfs(1,0);
solve(1,0);
cout<<m<<'\n';
for(auto pr:ans) cout<<pr.first<<' '<<pr.second<<'\n';
return 0;
}