CF527E Data Center Drama

CF527E Data Center Drama

我们可以发现很明显的两条使得一个图符合条件的要求:

  1. 一个点的度数为偶数。(显然,偶数+偶数=偶数)
  2. 总边数为偶数。(显然,若有奇数条边他造成的入度/出度的总数量都为奇数,但偶数相加还是偶数)

假设我们当前已经满足了以上两点,考虑如何构造方案。

(不可能有奇数个点的度数为奇数,这样总度数就为奇数了)

考虑利用这两条要求构造方案,我们不妨对图跑一个生成树,对于树边我们先不给他定向,对于非树边随意定向。

我们从生成树的叶子节点往上考虑,每次给通往父亲的边定向即可。

设我们当前考虑到了点\(u\),此时和他有关的边只差和父亲的没有定向。

由于\(u\)的总度数为偶数,则他此时不考虑父亲边的情况下,入度和出度必定有一个为奇数,我们用树边补上即可。

那么这样子操作过后,根节点的度数能否保证呢?

显然可以,因为总的入度/出度都为偶数,然后其他节点的入度/出度都为偶数,所以根节点也满足条件。

#include<bits/stdc++.h>
#define p_b push_back
#define m_p make_pair 
#define u first
#define v second
#define int long long
#define pii pair<int,int>
using namespace std;
inline int rd(){
	int x=0,f=1; char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar())if (ch=='-') f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
	return x*f;
}
const int N=1e5+5,INF=0x3f3f3f3f3f3f3f3f;
vector<pii> G,E[N];
vector<int> vec;
int n,m; 
int fa[N],du[N],in[N],out[N];
int find(int x){
	if(fa[x]==x) return x;
	return fa[x]=find(fa[x]);
}
void dfs(int x,int dad,int id){
	for(auto i : E[x]){
		if(i.first==dad) continue;
		dfs(i.first,x,i.second);
	}
	if(x==1) return;
	if((in[x]&1))G[id]=m_p(dad,x),in[x]++,out[dad]++;
	else G[id]=m_p(x,dad),in[dad]++,out[x]++;
}
signed main(){
	n=rd();m=rd();
	pii tmp;
	for(int i=1;i<=m;i++){
		tmp.u=rd(),tmp.v=rd();
		du[tmp.u]++,du[tmp.v]++;
		G.p_b(tmp);
	}
	for(int i=1;i<=n;i++)if((du[i]&1))vec.p_b(i);
	for(int i=0,j=1;j<(int)vec.size();i+=2,j+=2){
		G.p_b(m_p(vec[i],vec[j]));
		m++;
	}
	if(m&1) G.p_b(m_p(1,1)),m++;
	for(int i=1;i<=n;i++) fa[i]=i;
	int cnt=0;
	for(auto i : G){
		int fu=find(i.u),fv=find(i.v);
		if(fu==fv){
			out[i.u]++;
			in[i.v]++;
		}
		else{
			fa[fu]=fv;
			E[i.u].p_b(m_p(i.v,cnt));
			E[i.v].p_b(m_p(i.u,cnt));
		}
		cnt++;
	}
	dfs(1,0,-1);
	printf("%lld\n",m);
	for(auto i : G)printf("%lld %lld\n",i.u,i.v);
	return 0;	
}
posted @ 2024-07-19 16:35  123456xwd  阅读(33)  评论(0)    收藏  举报