Codeforces Round #375 (Div. 2)

来源:互联网 发布:淘宝女装店铺策划书 编辑:程序博客网 时间:2024/04/29 23:27

题意:

现有一张n个点m条边的无向图,你需要给这个无向图的所有边重新定向,使得新图所有点中,出度 = 入度的点尽可能地多,打印出任意一种可行的方案


solution:

首先,一张无向图中,度数为奇数的点一定是偶数个,因为无向图所有点的度数和一定是偶数

设度数为奇数的点有k个,分别是o1,o2,o3,...,ok

在图中新加入五向边(o1,o2),(o3,o4),(o5,o6),...,(ok-1,ok)

这样新图中所有点的度数均为偶数,一定存在欧拉回路

在这张图中跑欧拉回路算法,,求出欧拉回路,打印方案即可


欧拉回路朴素算法,,套圈法。。

任取一点开始随意dfs,找到一条从它出发并回到自身的路径,这样不能保证所有点都访问过

从这条路径上找,每找到一个还有边没访问过的点就把它另作起点重新dfs

处理欧拉回路时一遍处理一遍删边,复杂度O(m)

#include<iostream>#include<cstdio>#include<queue>#include<vector>#include<bitset>#include<algorithm>#include<cstring>#include<map>#include<stack>#include<set>#include<cmath>#include<ext/pb_ds/priority_queue.hpp>using namespace std;const int maxn = 222;const int maxm = maxn*maxn;int n,m,T,cnt,vis,top,du[maxn],pre[maxm],q[maxn][maxn],num[maxm],to[maxm],bo[maxm],s[maxn],last[maxn];void Add(int x,int y,int nu){to[++cnt] = y;pre[cnt] = last[x];last[x] = cnt;num[cnt] = nu;}void Dfs(int x,int fa){q[fa][++q[fa][0]] = x;int z = last[x];while (bo[num[z]] == vis) z = pre[z],last[x] = z;bo[num[z]] = vis;if (num[z] <= m)printf("%d %d\n",x,to[z]);if (to[z] != fa) Dfs(to[z],fa);}void Euler_cycle(int x){while (du[x]) {q[x][0] = 0;Dfs(x,x);queue <int> Q;for (int i = 1; i <= q[x][0]; i++) {du[q[x][i]] -= 2;if (du[q[x][i]]) Q.push(q[x][i]);}while (!Q.empty()) {int k = Q.front(); Q.pop();if (!du[k]) continue;Euler_cycle(k);}}}int main(){#ifdef DMCfreopen("DMC.txt","r",stdin);#endifcin >> T;while (T--) {scanf("%d%d",&n,&m);for (int i = 1; i <= n; i++) du[i] = last[i] = 0;cnt = 0; ++vis;for (int i = 1; i <= m; i++) {int x,y; scanf("%d%d",&x,&y);Add(x,y,i);Add(y,x,i);++du[x]; ++du[y];}int ans; ans = top = 0;for (int i = 1; i <= n; i++)if (du[i]&1) s[++top] = i;else ++ans;printf("%d\n",ans);int tot = m;for (int i = 1; i <= top; i += 2) {++tot;Add(s[i],s[i+1],tot);Add(s[i+1],s[i],tot);++du[s[i]]; ++du[s[i+1]];}for (int i = 1; i <= n; i++)if (du[i]) Euler_cycle(i);}return 0;}

0 0
原创粉丝点击