1. 程式人生 > >CF527E Data Center Drama(構造+歐拉回路)

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; 
        }
    }
}