欧拉路径&&欧拉回路
来源:互联网 发布:ps4实况2018网络对战 编辑:程序博客网 时间:2024/04/28 12:19
欧拉回路
无向图:图连通且每个点的度均为偶数
有向图:图连通且每个点入度等于出度
欧拉路径
无向图:图连通且只有两个奇点
有向图:图连通且一个点出度-入度为1,一个点入度-出度为1,其他点均入度等于出度
混合图的欧拉回路
1、随意定向
在混合图中,对于双向边的处理除了拆边之外,还有任意定向。先对全图的双向边进行任意定向,计算出度和入度,如果一个点的出度加入度是奇数的话,那么这个图中没有欧拉回路。虽然随意定向是没有依据的,但是可以使用这样的随机化处理方法,再使用恰当的调整方法构造出解。
2、自调整方法
将其中的一些边的方向调整回来,使所有的点的出度等于入度。但是有一条边的方向改变后,可能会改变一个点的出度的同时改变另一个点的入度,相当于一条边制约着两个点。同时有些点的出度大于入度,迫切希望它的某些点出边转向;而有些点的入度大于出度,迫切希望它的某些入边转向。这两条边虽然需求不同,但是他们之间往往一条边转向就能同时满足二者。
具体步骤:
1、另 x = |入度-出度| / 2,对于不同的点有不同的x值,这个x值代表它们在邻接表中相应调整x条就能让出度等于入度。
2、把图中的点转换为一个二分图,每个点的x值就是它们的点权。
3、源点S向所有出度>入度的点连边,汇点T向所有入度大于出度的点连边,将各自的点权转换为边权。
4、最后将原图中所有暂时定向的无向边加上一个1的容量,方向不变,而有向边不能改变方向,不需连边。
可以发现,从源点S出发的一个单位流将会把一个“无向边”的容量变为0,使得两端的点权各自减1,其实这就是在模拟一次对无向边方向的调整。当把图建好后,依靠最大流性质可以最大可能地无冲突调整边的方向,并最终使得每个点的点容量都达到满流。对那些图中出度等于入度的点做适当分析,它们作为一个“中间点”,由于流平衡性质,不会留下任何流量值,对于那些真正需要调整的点不会带来任何影响。最后检查从源点出发的每条边是否都满流,如果有一条边没有满流,说明有一个点没有调整到入度等于出度,于是整个图不存在欧拉回路。
例题
从一个点出发逛遍所有的路回到出发点,路分为单行路和双行路,这就是一个混合图求欧拉回路的问题。
#include <math.h>#include <vector>#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;const int MAXV = 1010;const int MAXE = 50010;const int INF = 0x3f3f3f3f;int n,m;int S,T;int totflow;//满流大小int dis[MAXV],vis[MAXV],Q[MAXV],h,t;int out[MAXV],in[MAXV],head[MAXV],cnt;struct edge{ int u,v,c,next;}node[MAXE];void Init(){ cnt = 0, totflow = 0; memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); memset(head, -1, sizeof(head));}void addedge(int u, int v, int c){//构建邻接表 node[cnt].v = v; node[cnt].c = c; node[cnt].next = head[u]; head[u] = cnt++;}int buildflow(){//创建最大流模型 int flag = true; S = 0, T = n+1; for(int i=1; i<=n; i++){ if((out[i] + in[i]) & 1) return 0; else if(out[i] > in[i]){ int c = (out[i] - in[i]) >> 1; addedge(S, i, c); addedge(i, S, 0); totflow += c; } else{ int c = in[i] - out[i]; addedge(i, T, c/2); addedge(T, i, 0); } } return 1;}int BFS(){//构建层次图 memset(dis, -1, sizeof(dis)); Q[1] = S, h = 0, t = 1; dis[S] = 0; while(h < t){ int u = Q[++h]; for(int i=head[u]; i!=-1; i=node[i].next){ int v = node[i].v, c = node[i].c; if(dis[v] == -1 && c){ dis[v] = dis[u] + 1; Q[++t] = v; if(v == T) return true; } } } return false;}int DFS(int id, int minflow){//Dinic算法过程 if(id == T) return minflow; int a = 0; for(int i=head[id]; i!=-1; i=node[i].next){ int v = node[i].v, c = node[i].c; if(c > 0 && dis[v] == dis[id] + 1 && (a = DFS(v, min(minflow, c)))){ node[i].c -= a; node[i^1].c += a; return a; } } return 0;}int Dinic(){ int tmp,ans = 0; while(BFS()){ while(tmp = DFS(S, INF)) ans += tmp; } return ans;}int main(){ int t; scanf("%d",&t); while(t--){ Init(); scanf("%d%d",&n,&m); while(m--){ int u,v,d; scanf("%d%d%d",&u,&v,&d); out[u]++, in[v]++; if(u == v) continue; if(d) continue; addedge(u, v, 1); addedge(v, u, 0); } int flag = buildflow(), ans = Dinic(); if(!flag) puts("impossible"); else if(ans >= totflow) puts("possible"); else puts("impossible"); } return 0;}
- 欧拉路径/回路
- 欧拉回路以及欧拉路径
- 欧拉路径&&欧拉回路
- 欧拉回路、欧拉路径
- 欧拉路径与欧拉回路
- hdu5348(欧拉回路+欧拉路径)
- 欧拉路径/欧拉回路
- 欧拉回路(欧拉路径)
- 欧拉路径-欧拉回路
- 欧拉回路(欧拉路径)
- 欧拉路径-欧拉回路
- 欧拉回路路径求解
- 欧拉回路+路径 POJ
- 欧拉回路/路径【总结】
- 欧拉回路--输出欧拉回路的路径
- POJ 2337 欧拉回路+欧拉路径+判断欧拉回路和路径
- 欧拉路径, 欧拉回路 USACO Riding the Fences
- 欧拉路径,欧拉回路,并查集
- 很不错的学习VIM的一篇文章,赶紧MARK。
- 判断是否为json对象
- king 选 太子
- LeetCode(45) Jump Game II
- JAVA - 泛型 vs CPLUSPLUS - 模板
- 欧拉路径&&欧拉回路
- 由浅入深了解Thrift(二)——Thrift工作原理
- Eclipse下python 中文乱码
- VC++ 创建、移动、管理solution
- LoadRunner安装破解license问题
- 一个简易的打log的c代码
- [JavaScript] 函数传参数分析
- redis基本操作
- 懒人码库简介