CF527E Data Center Drama(构造+欧拉回路)

题目链接

大意:

给你一个无向图。

要求加最少的边,然后给这些无向图的边定向,使得每一个点的出入度都是偶数。

输出定向后的边数和边集。

n<=10^5 m<=2*10^5


很巧妙的构造题……

可以发现答案的下界是\(度数为奇数的点个数m + 度数为奇数的点个数/2\)

因为是无向图,度数为奇数的点不可能有奇数个,于是考虑往每两个度数为奇数的点间连一条边。于是就可以愉快地跑欧拉回路啦。跑出来后在欧拉回路上构造像\(a\rightarrow b\leftarrow c\rightarrow d ……y\rightarrow x\leftarrow a\)这样的路径就行了,相当于把每个点的度数平分。

那如果构造出来的欧拉回路是类似于\(a- b- c- a\)这样,只有奇数条边,怎么分都分不好怎么办?起点和终点加个自环就OK了。

代码:

#include <bits/stdc++.h>
#define N 100005
using namespace std;
void rd(int &x){
    int y=0;char c=getchar();
    while(c<'0' || c>'9') c=getchar();
    while(c>='0' && c<='9') y=y*10+c-'0',c=getchar();
    x=y;
}
struct ed{
    int v,nxt;
    bool f;
}e[N<<3];
int head[N],cnt=1,deg[N],p[1000005],tot=0;
bool vis[N];
void add(int u,int v){
    e[++cnt]=(ed){v,head[u],0},head[u]=cnt;
    e[++cnt]=(ed){u,head[v],0},head[v]=cnt;
} 
void dfs(int u){
    for(int &i=head[u];i;i=e[i].nxt){
        int to=e[i].v;
        if(!e[i].f){
            e[i].f=1;
            e[i^1].f=1;
            dfs(to);
        }
    }
    p[++tot]=u;
}
int main(){
    int n,m,a,b,ans=0,lst=0,qwq=0,i;
    rd(n),rd(m);
    for(i=1;i<=m;++i){
        rd(a),rd(b);
        add(a,b);
        deg[a]++,deg[b]++;
    }
    for(i=1;i<=n;++i){
        if(deg[i]&1){
            ans++;
            if(ans%2==1) lst=i; 
            else if(lst) add(lst,i);
        }
    }
    m+=ans/2;
    if(m&1) add(1,1),m++;
    printf("%d\n",m);
    for(i=1;i<=n;++i){
        if(!vis[i]){
            tot=qwq=0;
            dfs(i);
            for(i=1;i<tot;++i) printf("%d %d\n",p[i+qwq],p[i+(!qwq)]),qwq^=1; 
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/PsychicBoom/p/10120529.html
今日推荐