POJ 1637 混合图求欧拉回路 最大流实现
前面讲过了无向图,有向图求欧拉回路,欧拉通路的做法。可以直接根据度数来判断,当然前提是这是一个连通图。
这道题既有无向边,又有有向边,然后求欧拉回路。
采用的方法是最大流。
具体处理方法。
首先,我们对无向边,进行随意定边。定完边之后,求出每个点的出度入度。如果某个点的出度入度之差为奇数,那么就无法形成欧拉回路。
接下来所有的点的度数之差都是偶数了,对于有向边,我们不需要处理。
对于无向边,我们给初始随意定的边的方向,流量+1,即如果一条无向边,a - b,我们初始给他定边是a -> b,那么我们将a -> b的流量+1。
然后对于每个入度出度之差为偶数的点,如果出度大于入度。那么我们连一条S到该点的边,流量为 (出度 - 入度)/ 2 。
同理,对于入度大于出度的边,我们连一条该点到T的边,流量为(入度- 出度)/ 2 。
接下来我们跑一遍最大流即可以了。
如果该图是满流的话,那么证明存在欧拉回路。否则不存在。
具体证明请看这里。http://zhyu.me/acm/zoj-1992-and-poj-1637.html
CODE:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <stack>
#include <map>
#include <iomanip>
#define PI acos(-1.0)
#define Max 2505
#define inf 1<<28
#define LL(x) ( x << 1 )
#define RR(x) ( x << 1 | 1 )
#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#define PII pair<int,int>
using namespace std; inline void RD(int &ret) {
char c;
do {
c = getchar();
} while(c < '0' || c > '9') ;
ret = c - '0';
while((c=getchar()) >= '0' && c <= '9')
ret = ret * 10 + ( c - '0' );
}
inline void OT(int a){
if(a >= 10)OT(a / 10) ;
putchar(a % 10 + '0') ;
}
#define N 1005
#define M 100005
struct ed{
int s , e , flag ;
}road[M] ;
int in[N] ,out[N] ; struct kdq{
int e , next ,c ;
}ed[M] ; int head[N] ,num ; void add(int s ,int e ,int c){
ed[num].e = e ;
ed[num].c = c ;
ed[num].next = head[s] ;
head[s] = num ++ ;
ed[num].e = s ;
ed[num].c = 0 ;
ed[num].next = head[e] ;
head[e] = num ++ ;
} void init(){
mem(head , -1) ;
mem(in , 0) ;
mem(out , 0) ;
}
int S , T ;
int dis[N] ,qe[M] ,deep[N] ;
int n , m ; /***dinic模版***/
int dinic_bfs(){
mem(deep, -1) ;
deep[S] = 0 ;
int h = 0 , t = 0 ;
qe[h ++ ] = S ;
while(h > t){
int tt = qe[t ++ ] ;
for (int i = head[tt] ; ~i ; i = ed[i].next ){
int e = ed[i].e ;
int c = ed[i].c ;
if(c > 0 && deep[e] == -1){
deep[e] = deep[tt] + 1 ;
qe[h ++ ] = e ;
}
}
}
return deep[T] != -1 ;
}
int dinic_dfs(int now ,int f){
if(now == T)return f ;
int flow = 0 ;
for (int i = head[now] ; ~i ; i = ed[i].next ){
int e = ed[i].e ;
int c = ed[i].c ;
if((f - flow) > 0 && c > 0 && deep[e] == deep[now] + 1 ){
int mm = min(f - flow ,c) ;
int nn = dinic_dfs(e , mm) ;
flow += nn ;
ed[i].c -= nn ;
ed[i ^ 1].c += nn ;
}
}
if(flow == 0)deep[now] = -2 ;
return flow ;
} int dinic(){
int MaxFlow = 0 ;
while(dinic_bfs()){
MaxFlow += dinic_dfs(S ,inf) ;
}
return MaxFlow ;
}
/******/
int main() {
int t ;
cin >> t ;
while(t -- ){ cin >> n >> m ;
init() ;
S = 0 , T = n + 1 ;
for (int i = 1 ; i <= m ; i ++){
RD(road[i].s) ;RD(road[i].e) ;RD(road[i].flag) ;
out[road[i].s] ++ ;
in[road[i].e] ++ ;
}
bool flag = 0 ;
for (int i = 1 ; i <= n ; i ++ ){
if(abs(in[i] - out[i]) & 1){//存在度数之差为奇数的点
puts("impossible") ;
flag = 1 ;
break ;
}
}
if(flag)continue ;
for (int i = 1 ; i <= m ;i ++ ){
if(road[i].flag)continue ;
add(road[i].s ,road[i].e , 1) ;//初始定边我都是按a -> b的方向
}
int MF = 0 ;
for (int i = 1 ; i <= n ; i ++ ){
if(out[i] > in[i]){
add(S , i , (out[i] - in[i]) / 2 ) ;
MF += (out[i] - in[i]) / 2 ;
}
else if(in[i] > out[i]){
add(i , T , (in[i] - out[i]) / 2) ;
}
}
int MaxFlow = dinic() ;
if(MaxFlow == MF){
puts("possible") ;
}
else puts("impossible") ;
}
return 0 ;
}
POJ 1637 混合图求欧拉回路 最大流实现的更多相关文章
- POJ 1637 混合图的欧拉回路判定
题意:一张混合图,判断是否存在欧拉回路. 分析参考: 混合图(既有有向边又有无向边的图)中欧拉环.欧拉路径的判定需要借助网络流! (1)欧拉环的判定:一开始当然是判断原图的基图是否连通,若不连通则一定 ...
- bzoj2095: [Poi2010]Bridges(二分+混合图求欧拉回路)
传送门 这篇题解讲的真吼->这里 首先我们可以二分一个答案,然后把所有权值小于这个答案的都加入图中 那么问题就转化为一张混合图(既有有向边又有无向边)中是否存在欧拉回路 首先 无向图存在欧拉回路 ...
- POJ 1637 混合图欧拉回路
先来复习一下混合图欧拉回路:给定一张含有单向边和双向边的图,使得每一点的入度出度相同. 首先对于有向边来说,它能贡献的入度出度是确定的,我们不予考虑.对于无向图,它可以通过改变方向来改变两端点的出入度 ...
- poj 1637 混合图欧拉回路 学习笔记
题目大意 求混合图是否存在欧拉回路 做法 有向边我们只有增加入度出度 对于无向边,我们给它设定一个初始方向 如果不能满足|入度-出度|为偶数,无解 然后在网络流图中, 设设定方向的反向连一条边,表示反 ...
- 紫书 例题 11-13 UVa 10735(混合图的欧拉回路)(最大流)
这道题写了两个多小时-- 首先讲一下怎么建模 我们的目的是让所有点的出度等于入度 那么我们可以把点分为两部分, 一部分出度大于入度, 一部分入度大于出度 那么显然, 按照书里的思路,将边方向后,就相当 ...
- [POJ1637]混合图的欧拉回路判定|网络流
混合图的欧拉回路判定 上一篇正好分别讲了有向图和无向图的欧拉回路判定方法 如果遇上了混合图要怎么做呢? 首先我们思考有向图的判定方法:所有点的出度=入度 我们可以先为无向边任意定一个向,算出此时所有顶 ...
- UVA 10735 Euler Circuit 混合图的欧拉回路(最大流,fluery算法)
题意:给一个图,图中有部分是向边,部分是无向边,要求判断是否存在欧拉回路,若存在,输出路径. 分析:欧拉回路的定义是,从某个点出发,每条边经过一次之后恰好回到出发点. 无向边同样只能走一次,只是不限制 ...
- UVa 10735 (混合图的欧拉回路) Euler Circuit
题意: 给出一个图,有的边是有向边,有的是无向边.试找出一条欧拉回路. 分析: 按照往常的思维,遇到混合图,我们一般会把无向边拆成两条方向相反的有向边. 但是在这里却行不通了,因为拆成两条有向边的话, ...
- bzoj 2095: [Poi2010]Bridges(二分法+混合图的欧拉回路)
[题意] 给定n点m边的无向图,对于边u,v,从u到v边权为c,从v到u的边权为d,问能够经过每条边一次且仅一次,且最大权值最小的欧拉回路. [思路] 二分答案mid,然后切断权值大于mid的边,原图 ...
随机推荐
- poj 3349 (最小表示法)
开始按hash做的 交上去就wa 但是和标称拍了半天也没有不一样的 可能是生成的数据太水了吧... #include<iostream> #include<cstdio> #i ...
- hdu 1728
//hdu 1728 //这个是一道很经典的迷宫题了,思路感觉...取起点和终点,判断连线是否超过n个弯, //先是从起点出发,上下左右四个方向搜索,找到一条路,把那条路的第一个点压入队列 //然后沿 ...
- 自己动手写easyui的checkbox
最近项目中用到了easyui这个框架,找了一圈也没有找到checkbox list控件,被迫只能自己实现了,为了便于复用,自己封装了下,有需要的,直接拿去用吧.有意见或建议的,欢迎指教啊. 调用示例 ...
- PHP对表单提交特殊字符的过滤和处理
PHP关于表单提交特殊字符的处理方法做个汇总,主要涉及htmlspecialchars/addslashes/stripslashes/strip_tags/mysql_real_escape_str ...
- eclipse - copy类的全名
由于多次操作,感觉eclipse应该提供这个功能,网上搜一下,发现需要安装插件. 下载地址为 http://www.jave.de/eclipse/copyfully/copyfully_1.2.0. ...
- MySql中的时间类型datetime,timestamp,date,year比较
MySQL日期类型.日期格式.存储空间.日期范围比较.日期类型 存储空间 日期格式 日期范围------------ --------- ...
- 你好,C++(30)“大事化小,小事化了”5.4.3 工资程序成长记:函数
5.4.3 工资程序成长记:函数 自从上次小陈“程序员”的工资程序得到老板的夸奖,口头许诺给他涨工资以后,老板再也没有找过他,涨工资的事自然也就没有下文了.这天,老板又突然召他去办公室.这下可把小陈高 ...
- mongodb安装服务
一.准备工作 1:下载: http://www.mongodb.org/downloads 2:解压到ZIP到 D:\Mongodb ,在此目录下再建立2个目录 D:\Mongodb\db和D ...
- PLSQL developer连接不上64位Oracle的解决方法
PLSQL developer连接不上64位Oracle的解决方法 64位下装Oracle 11g 64位,PLSQL Developer使用出现问题. 问题描述: 登录对话框中,数据库下拉框为空: ...
- js获取url?后的参数
function GetRequest() { var url = location.search; //获取url中"?"符后的字串 var theRequest = new O ...