2015多校.MZL's endless loop(欧拉回路的机智应用 || 构造)
2015-08-05 10:30
225 查看
MZL's endless loop
Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 898 Accepted Submission(s): 178
Special Judge
[align=left]Problem Description[/align]
As we all kown, MZL hates the endless loop deeply, and he commands you to solve this problem to end the loop.
You are given an undirected graph with n vertexs and m edges. Please direct all the edges so that for every vertex in the graph the inequation |out degree − in degree|≤1 is satisified.
The graph you are given maybe contains self loops or multiple edges.
[align=left]Input[/align]
The first line of the input is a single integer T, indicating the number of testcases.
For each test case, the first line contains two integers n and m.
And the next m lines, each line contains two integers ui and vi, which describe an edge of the graph.
T≤100, 1≤n≤105, 1≤m≤3∗105, ∑n≤2∗105, ∑m≤7∗105.
[align=left]Output[/align]
For each test case, if there is no solution, print a single line with −1, otherwise output m lines,.
In ith line contains a integer 1 or 0, 1 for direct the ith edge to ui→vi, 0 for ui←vi.
[align=left]Sample Input[/align]
2
3 3
1 2
2 3
3 1
7 6
1 2
1 3
1 4
1 5
1 6
1 7
[align=left]Sample Output[/align]
1
1
1
0
1
0
1
0
1
#include<vector> #include<string.h> #include<stdio.h> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int M = 3e5 + 10 ; struct Edge { int v ; bool vis ; int nxt ; Edge () {} Edge (int v , int vis , int nxt) : v(v) , vis(vis) , nxt(nxt) {} }e[M << 2] ; int H[M] , E ; int n , m ; int in[M] ; int res[M << 1] ; void addedge (int u , int v) { e[E] = Edge (v , 0 , H[u]) ; H[u] = E ++ ; e[E] = Edge (u , 0 , H[v]) ; H[v] = E ++ ; } void dfs (int u) { for (int &i = H[u] ; ~i ; ) { int v = e[i].v ; if (e[i].vis) { i = e[i].nxt ; continue ; } e[i].vis = 1 ; e[i^1].vis = 1 ; res[i >> 1] = i & 1 ; in[v] -- ; in[u] -- ; i = e[i].nxt ; dfs (v) ; } } void mend () { int p = -1 ; for (int i = 1 ; i <= n ; i ++) { if (in[i] & 1) { if (p == -1) { p = i ; } else { addedge (p , i) ; in[p] ++ ; in[i] ++ ; p = -1; } } } } void solve () { mend () ; for (int i = 1 ; i <= n ; i ++) { if(in[i]) { dfs (i) ; } } for (int i = 0 ; i < m ; i ++) printf ("%d\n" , res[i]) ; } int main () { int T ; scanf ("%d" , &T ) ; while (T --) { scanf ("%d%d" , &n , &m) ; for (int i = 0 ; i <= n ; i ++) H[i] = -1 ; E = 0 ; for (int i = 0 ; i < m ; i ++) { int u , v ; scanf ("%d%d" , &u , &v) ; addedge (u , v) ; in[u] ++ ; in[v] ++ ; } solve () ; } return 0 ; }
View Code
根据“欧拉回路”的定义,当连通图所有点的度数为偶数时,那么必然会存在一条路线,使得经过所有点并且每条边只经过一次
[align=left]所以很明显如果我们能在构造是利用好这个性质的话,整个复杂度为O(m + k)[/align]
[align=left]为什么还有一个常数k?你很容易回发现,题目给定的边数不一定回使每个点的度数为 偶数 , 那么怎么办呢?补边咯,把两两为奇数度的点之间加一条边即可。[/align]
[align=left]那么你可定又会有疑问了,这样添加边会不会导致最后的 “题设的条件” 收到影响?[/align]
[align=left]没事的,因为题目说了 |入度 - 出度| <= 1 ,因为你构造的是欧拉回路,所以找到后的欧拉回路肯定满足所有点|入度 - 出度| = 0 , 而我们在每个点上最多只加了[/align]
[align=left]一条边,所以去掉后,肯定 <= 1 的。[/align]
[align=left] [/align]
[align=left]铭神说,构造回路时,因为每个点可能会被遍历到多次,这样如果姿势不对,很容易导致又把那个点的所有边遍历一遍,导致复杂度又变成O(n*m),所以去仔细[/align]
[align=left]看代码吧233[/align]
(欧拉通路:除了两个点外度数为奇数,其他点的度数为偶数)
相关文章推荐
- Linux 进程调度小结
- Linux 进程调度小结
- POJ 3675 Telescope(计算几何)
- linux curl 或者 命令行 的用法
- Linux关机命令详解
- Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 Web modules
- opencv学习(四)书本《学习Opencv》(中文版)第四章的样例Ex4-2(opencv3.0.0+VS2012+win7)
- Linux 因修改/etc/ssh权限导致的ssh不能连接异常解决方法
- 初学git:用git bash往github push代码
- Linux 进程间通信 --- 信号通信 --- signal --- signal(SIGINT, my_func); --- 按键驱动异步通知
- tomcat自动加载改变的class文件(无需重启tomcat)
- LSD在opencv中的实现
- 安装OpenResty
- 在 Linux 下使用 rfkill 软开关蓝牙及无线功能
- 7月末周全球域名商(国际域名)新增注册量TOP20
- 使用七牛云存储在网站中进行图片外链
- 积累linux常用命令大全
- linux环境安装Nginx
- linux grep命令详解
- linux grep命令