codeforces 723E (欧拉回路)

Problem One-Way Reform

题目大意

  给一张n个点,m条边的无向图,要求给每条边定一个方向,使得最多的点入度等于出度,要求输出方案。

解题分析

  最多点的数量就是入度为偶数的点。

  将入度为奇数的点每两个组成一队,连一条无向边,之后求出欧拉回路即可。

参考程序

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <string>
  8 #include <vector>
  9 #include <cstdio>
 10 #include <cstdlib>
 11 #include <cstring>
 12 #include <cassert>
 13 #include <iostream>
 14 #include <algorithm>
 15 #pragma comment(linker,"/STACK:102400000,102400000")
 16 using namespace std;
 17
 18 #define N 1000
 19 #define E 50000
 20 #define LL long long
 21 #define lson l,m,rt<<1
 22 #define rson m+1,r,rt<<1|1
 23 #define clr(x,v) memset(x,v,sizeof(x));
 24 #define bitcnt(x) __builtin_popcount(x)
 25 #define rep(x,y,z) for (int x=y;x<=z;x++)
 26 #define repd(x,y,z) for (int x=y;x>=z;x--)
 27 const int mo  = 1000000007;
 28 const int inf = 0x3f3f3f3f;
 29 const int INF = 2000000000;
 30 /**************************************************************************/
 31
 32 int T,n,m,sum;
 33 int lt[N],deg[N],f[N],dict[E];
 34 struct line{
 35     int u,v,nt,flag;
 36 }eg[E];
 37 void add(int u,int v)
 38 {
 39     eg[++sum]=(line){u,v,lt[u],0}; lt[u]=sum; deg[v]++;
 40 }
 41 vector <int> vct,path;
 42 stack <int> Q;
 43 void dfs(int u)
 44 {
 45     int v=0;
 46     Q.push(u);
 47     f[u]=1;
 48     for (int i=lt[u];i;i=eg[i].nt)
 49     {
 50         if (eg[i].flag) continue;
 51         eg[i].flag=eg[i^1].flag=1; dict[i/2]=i; lt[u]=i;
 52         v=eg[i].v;
 53         dfs(v);
 54         break;
 55     }
 56 }
 57 void work(int S)
 58 {
 59     while (!Q.empty()) Q.pop();
 60     Q.push(S);
 61     while (!Q.empty())
 62     {
 63         int u=Q.top(),flag=0; Q.pop();
 64         for (int i=lt[u];i;i=eg[i].nt)
 65         {
 66             if (eg[i].flag) continue;
 67             flag=1;
 68             break;
 69         }
 70         if (flag) dfs(u); else path.push_back(u);
 71     }
 72 }
 73 int main()
 74 {
 75     cin>>T;
 76     while (T--)
 77     {
 78         cin>>n>>m;
 79         int ans=n;
 80         rep(i,1,n) deg[i]=lt[i]=0; sum=1;
 81         rep(i,1,m)
 82         {
 83             int u,v;
 84             scanf("%d%d",&u,&v);
 85             add(u,v); add(v,u);
 86         }
 87         vct.clear(); path.clear();
 88         rep(i,1,n) if (deg[i] & 1)
 89         {
 90             ans--;
 91             vct.push_back(i);
 92         }
 93         for (int i=0;i<vct.size();i+=2)
 94         {
 95             add(vct[i],vct[i+1]);
 96             add(vct[i+1],vct[i]);
 97         }
 98         clr(f,0);
 99         rep(i,1,n) if (f[i]==0) work(i);
100         printf("%d\n",ans);
101         rep(i,1,m) printf("%d %d\n",eg[dict[i]].u,eg[dict[i]].v);
102         //for (auto v:path) printf("%d ",v);
103     }
104 }

时间: 2024-10-08 06:25:19

codeforces 723E (欧拉回路)的相关文章

Codeforces 723e [图论][欧拉回路]

/* 不要低头,不要放弃,不要气馁,不要慌张. 题意: 给你一个有n个点,m条边的无向图,给每条边规定一个方向,使得这个图变成有向图,并且使得尽可能多的点入度与出度相同. 输出有多少个这样的点并且输出有向图. 思路: 1.针对每个连通分支. 2.所有点入度与出度相同,显然这是欧拉回路存在的判定定理,但是欧拉回路的另外一个等价定理是所有点的度数是偶数.那如果给我们的图中的某些点是奇数度该怎么办. 3.显然原图中给的点如果度数是奇数,那么该点的入度与出度一定不相同. 4.根据握手定理,无向图中度数是

CodeForces 723E One-Way Reform

构造. 有一种十分巧妙的方法可以使图中所有度数为偶数的节点,经过每条边定向后,出度和入度都相等. 首先统计每个节点的度数,将度数为奇数的节点与编号为$n+1$的节点连边,这样一来,这张新图变成了每个节点的度数都是偶数的图,必然存在欧拉回路.任意一条欧拉回路都使得原图中度数为偶数的节点的出度与入度相等. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cs

CodeForces 21D Traveling Graph 状压dp+欧拉回路

题目链接:点击打开链接 题意: 给定n个点m条边的无向图 求从1点开始经过每条边至少一次最后回到1点的最小路程 显然就是找一条路径可重复的欧拉回路 思路: 首先对于欧拉回路的结论是:所有点的度数都为偶数 因为所有边至少经过一次,那么可以把题意转换成加最少多少条边使得图满足以上结论 而加的边目的是为了把奇度数转成偶度数,先floyd一下得到任意点间加边的最小花费 dp[i]表示状态i下度数都为偶数的最小花费. 状压dp,把i状态下,所有未选择的点中挑2个奇度数的转移即可. #include <cs

Codeforces 91C Ski Base 加边求欧拉回路数量

题目链接:点击打开链接 题意: 给出n个点m条无向边的图 开始图里没有边,每次加一条边,然后输出图里欧拉回路的条数. 思路: We will count the number of ski bases including the base consisted of empty subset of edges (before printing just subtract one). In the beginning the number of bases is equal to 1. If we

Codeforces 527E Data Center Drama(欧拉回路)

题意: 给定一个无向图连通图,把这个的无向边变成有向边,并添加最少的有向边使这个图每个结点的出度为偶数. Solution: 题目很长,并且很多条件说的不太直接,确实不太好懂. 首先先看得到的无向图,是不是可以不加边就满足题目要求. 可以想到对于一个无向图,当所有点的度数为偶数时,图中存在欧拉回路.那么对于一个存在欧拉路的无向图似乎可以以某种方式构造出满足条件的有向边.假设图中有欧拉回路1 2 3 4 1, 可以构造边2->1,2->3,4->3,4->1满足条件. 而对于不存在欧

codeforces #547D Mike and Fish 欧拉回路

题目大意:给定平面上的n个点,要求将每个点染成红色/蓝色,使得每行/每列的红色点数和蓝色点数之差≤1 将每一个横坐标/纵坐标看做一个点,每个点看做一条连接两个坐标的边 现在我们要将每条边染色使得每个点连接的所有边中两种颜色之差≤1 首先找到度数为奇数的点 这样的点一定有偶数个 将度数为奇数的点两两配对连边,这样所有点的度数就都是偶数了 然后对于每个连通块,任选一个初始度数为奇数的点(不存在则任选一个度数为偶数的点),求一条欧拉回路(如果起始点初始度数为奇数则要求先遍历新连接的边),然后将路径上的

Codeforces 1186F - Vus the Cossack and a Graph 模拟乱搞/欧拉回路

题意:给你一张无向图,要求对这张图进行删边操作,要求删边之后的图的总边数 >= ceil((n + m) / 2), 每个点的度数 >= ceil(deg[i] / 2).(deg[i]是原图中i的度数) 思路1:模拟 + 乱搞 直接暴力删就行了,读入边之后随机打乱一下就很难被hack了. 代码: #include <bits/stdc++.h> #define LL long long #define INF 0x3f3f3f3f #define db double #defin

CodeForces 367 C Sereja and the Arrangement of Numbers 欧拉回路

Sereja and the Arrangement of Numbers 题解: ummm. 在一副图中,如果全部点的度数是偶数/只有2个点是奇数,则能一笔画. 考虑图的点数k为奇数的时候,那么每个点的度数都是偶数点,所以就是可以一笔画,答案为 1 +k * (i - kll) / 2; k为偶数的时候,所有的点是奇数点,我们保留2个点是奇数点,将其他的点改为偶数点,就可以一笔画了.  1 +k * (i - kll) / 2 + k/2 - 1. 代码: #include<bits/stdc

Codeforces 405E DFS

这个题目要求把一个无向连通图里面的所有边,分成 两个一对,只能出现一次,而且一对边必须是连在一起的,点可以复用  但边不可复用 可解条件很易得,因为图是连通的,只要边数为偶数即可. 一开始我借着做欧拉回路的方法,直接DFS暴搜,沿路做标记,遇到未标记的连续两条边 输出即可 不过 事实证明这个算法是错的 暴搜能成立只是建立在图上的边可以存在很多个边对里,但肯定有图不满足这种条件 其实解决方法也就是在DFS的基础上对特殊边进行下考虑即可 即每次对某个点,对子节点进行dfs,如果发现子节点下面有落单的