【Codeforces 527E】Data Center Drama

欧拉回路,构造。

题目大意:

给定一张无向连通图,要求加入最少的边,并给无向图定向,使得每个点的入度和出度都是偶数。输出方案。

题解:

每个点的度数为偶数,则每个连通块都为欧拉图。

考虑原来的无向图,可能存在度数为奇数的点,这样的点一定有偶数个。我们将其两个两个配对并连边,可以使所有点的度数都是偶数。

然后求欧拉回路。对于一个欧拉回路,我们将路径上的点依次排列以后,按照一条边从左到右,一条边从右到左的顺序连边,即可使除了起点以外的所有点都满足偶数的度数条件。起点如果存在度数为奇数的情况,可以连一条自环解决。

由于原图是无向连通图,所以这样的答案一定是最小的。

Code:

#include<cstdio>
#include<vector>
using namespace std;
const int N=4e5+5;
struct edge{
    int to,nxt,id;
}e[N<<1];
int cnt=1,head[N],n,m,deg[N],top;
bool vis[N];
int sta[N];
vector<pair<int,int> >vc;
bool vs[N];
inline void addedge(int u,int v,int w){
    e[++cnt]=(edge){v,head[u],w},head[u]=cnt;
    e[++cnt]=(edge){u,head[v],w},head[v]=cnt;
}
void dfs(int now){
    for(int&i=head[now];i;i=e[i].nxt)
    if(!vis[e[i].id]){
        vis[e[i].id]=1;
        --deg[e[i].to],--deg[e[i^1].to];
        dfs(e[i].to);
    }
    sta[++top]=now;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i){
        int u,v;
        scanf("%d%d",&u,&v);
        ++deg[u],++deg[v];
        addedge(u,v,i);
    }
    int lst=0;
    for(int i=1;i<=n;++i)if(deg[i]&1){
        if(!lst)lst=i;else addedge(lst,i,++m),lst=0,++deg[lst],++deg[i];
    }
    for(int i=1;i<=n;++i)if(deg[i]){
        top=0;
        dfs(i);
        if(top&1^1)sta[++top]=sta[1];
        for(int i=1;i<top;++i)
        if(i&1)vc.emplace_back(sta[i],sta[i+1]);else vc.emplace_back(sta[i+1],sta[i]);
    }
    printf("%u\n",vc.size());
    for(auto i:vc)
    printf("%d %d\n",i.first,i.second);
    return 0;
}