poj 1637 混合图的欧拉回路
来源:互联网 发布:平板蓝牙软件下载 编辑:程序博客网 时间:2024/06/05 01:51
混合图:即有的边有向,有的边无向。
定义:
对于图G的一个回路,若它恰通过G中每条边一次,则称该回路为欧拉(Euler)回路。 具有欧拉回路的图称为欧拉图(简称E图)。
定理:
一个无向图是欧拉图,当且仅当该图所有顶点度数都是偶数。
一个有向图是欧拉图,当且仅当该图所有顶点度数都是0。
有向图存在欧拉回路的充要条件:基图(把所有有向边变成无向边以后得到的图)连通,且每个点的出度等于入度。
所以求混合图的关键是:判断能否存在一个定向,使得每个节点的入度等于出度。
因此可以用网络流来做。建边方法,黑书上有两种,这里讲第二种,更好一点的。图的点数为n + 2,边数为 m + n,其中,n为原点数,m为原边数。
黑书上的讲的我没看太懂,按照我自己的理解,讲一下建图过程。
在原图中,首先给每条无向边任意定向,构成一个有向图,计算每个点的度deg,入度为正,出度为负,如果某个点的deg为奇数,显然不存在欧拉回路。由于原来的有向边,不能更改方向,无用,删了,对原图中的无向边定向后构成的有向图,如果点 i 到j 有一条弧,弧< i , j >容量加1(i 到 j 有多条边的时候,即有重边,可以一条边,多容量代替) 增加源点S,汇点T,对于每个点 i ,如果deg < 0,即出度大于入度,从S引一条弧到 i ,容量为(- deg ) / 2;如果deg > 0, 即入度大于出度,从 i 引一条弧到 T,容量为 deg / 2,如果deg = 0,就不用建边了。求新网络的最大流。如果从S出发的所有弧满载,则欧拉回路存在,把所有的有流的弧全部反向(如果某条边容量大于1,流量为几,反向几条边就可以了),把原图中的有向边再重新加入,就得到了一个有向欧拉回路。
满载是为了流量平衡,为了每个顶点的入度和出度相等。
为什么把有流边反向,就能得到一个欧拉回路呢?
想一想:如果有流边<u, v>反向,则deg[u]就增加了2, deg[v]减少了2, 这就是为什么开始加弧的时候为什么deg要除以2的原因了,每增加一个流量,就有一条起点到终点的路径,把路径上的所有点都反向,则起点的度增加了2, 终点的度减少了2, 中间点度数不变,而起点如果有这条流量,就代表他的出度大,入度小,需要更改临边来使得最终出度等于入度,最大流的这个性质正好满足,如果所有S到v的弧满流了,那么经过上面的操作,v点的出度必然等于入度,如果所有从S出发的弧都满流了,那么就找到以一种定向方式使得原图得到了一个有向欧拉回路。
引子这篇blog 点击打开链接
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<stack>#include<cmath>using namespace std;const int N = 210;const int M = 1010;const int inf = 0x3f3f3f3f;int ind[N],outd[N],head[N],dis[N];int num,n,m,maxflow,totflow,source,sink;struct Edge{ int to,flow,next;}edge[M*3];void add(int from,int to,int flow){ edge[num].to = to; edge[num].flow = flow; edge[num].next = head[from]; head[from] = num++;}void add_graph(int from,int to,int flow){ add(from,to,flow); add(to,from,0);}void init(){ memset(head,-1,sizeof(head)); memset(outd,0,sizeof(outd)); memset(ind,0,sizeof(ind)); num = 0;}void input(){ int from,to,type; scanf("%d %d",&n,&m); for(int i = 0 ; i < m ;i++) { scanf("%d %d %d",&from,&to,&type); ind[to]++; outd[from]++; if(from != to && !type) { add_graph(from,to,1); } }}int build(){ totflow = 0,source = 0,sink = n + 1; for(int i = 1 ; i <= n ; i++) { if((ind[i] + outd[i]) & 1) { return 0; } else if(outd[i] > ind[i]) { int dis = (outd[i] - ind[i]) >> 1; totflow += dis; add_graph(source,i,dis); } else { int dis = (ind[i] - outd[i]) >> 1; add_graph(i,sink,dis); } } return 1;}int bfs(){ memset(dis,0,sizeof(dis)); queue<int>q; dis[source] = 1; q.push(source); while(!q.empty()) { int cur = q.front(); q.pop(); if(cur == sink) { return 1; } for(int i = head[cur] ; i != -1 ; i = edge[i].next) { int to = edge[i].to; int flow = edge[i].flow; if(!dis[to] && flow) { dis[to] = dis[cur] + 1; q.push(to); } } } return 0;}int dfs(int cur,int cp){ if(cur == sink) { return cp; } int tmp = cp; int t; for(int i = head[cur] ; i != -1 && tmp ; i = edge[i].next) { int to = edge[i].to; int flow = edge[i].flow; if(dis[to] == dis[cur] + 1 && flow) { t = dfs(to,min(tmp,flow)); edge[i].flow -= t; edge[i^1].flow += t; tmp -= t; } } return cp - tmp;}void dinic(){ maxflow = 0; while(bfs()) { maxflow += dfs(source,inf); }}int main(){ #ifdef LOCAL freopen("in.txt","r",stdin); #endif // LOCAL int ncase; scanf("%d",&ncase); while(ncase--) { init(); input(); int flag = build(); if(flag) { dinic(); if(maxflow >= totflow) { cout<<"possible"<<endl; } else { cout<<"impossible"<<endl; } } else { cout<<"impossible"<<endl; } } return 0;}
- 混合图的欧拉回路 POJ 1637
- poj 1637 & zoj 1992 混合图的欧拉回路
- POJ 1637 混合图的欧拉回路
- POJ 1637 Sightseeing tour (混合图的欧拉回路)
- poj 1637 求混合图的欧拉回路
- POJ 1637 混合图的欧拉回路
- poj 1637 混合图的欧拉回路
- POJ 1637 Sightseeing tour(混合图的欧拉回路)
- POJ 1637 Sightseeing tour 混合图的欧拉回路
- POJ 1637 混合图的欧拉回路 网络流
- poj 1637 Sightseeing tour 混合图的欧拉回路
- POJ 1637 混合欧拉回路
- poj 1637 判断混合图是否存在欧拉回路
- 欧拉回路(混合图的欧拉回路)
- poj 1637(求混合图的欧拉回路是否存在:构造网络流求解)
- Poj 1637 Sightseeing tour (混合图的欧拉回路判定)
- Sightseeing tour (poj 1637 混合图的欧拉回路)
- POJ-1637 Sightseeing tour(通过网络流判定混合图的欧拉回路)
- 1410132036-hd-Keep on Truckin'
- 每天一个linux命令(12):more命令
- UIView的layoutSubviews和drawRect方法何时调用
- 想要做好一个高质量内容的页面,你需要精通什么?
- 计算一个数字的立方根,不使用库函数
- poj 1637 混合图的欧拉回路
- 网站链接包含关键字好处多多
- 无法导入android 工程--提示项目已经存在
- 【综述】(MIT博士)林达华老师-"概率模型与计算机视觉”
- 赛珍珠大地读书小感
- 百度快照更新与排名的关系
- Python For Data Analysis笔记
- JAVA wait(), notify(),sleep详解
- poj 2151 Check the difficulty of problems (概率dp)