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的边,原图 ...
随机推荐
- 各版本IIS安装方法
各版本IIS安装方法 Windows 2000 V5.0 将操作系统安装光盘放入光驱,打开“控制面板”→“添加或删除程序”→“添加/删除 Windows 组件”,勾选“Internet信息服务(I ...
- JS判断图片是否加载完成三种方式
1.img的complete属性 轮询不断监测img的complete属性,如果为true则表明图片已经加载完毕,停止轮询.该属性所有浏览器都支持. <p id="p1"&g ...
- 使用CAEmitterLayer实现下雪效果
效果图: 代码部分: #import "ViewController.h" @interface ViewController () @end @implementation Vi ...
- 带格式导出数据到Excel
导出按钮事件 protected void Button1_Click(object sender, EventArgs e) { Response.Clear(); ...
- Java接口和抽象类的实现方法
一.java中的接口本质上是加约束的抽象类 //抽象类 public abstract class AExample { public abstract int add(int x,int y); p ...
- Python自动化运维之8、正则表达式re模块
re模块 正则表达式使用单个字符串来描述.匹配一系列符合某个句法规则的字符串,在文本处理方面功能非常强大,也经常用作爬虫,来爬取特定内容,Python本身不支持正则,但是通过导入re模块,Python ...
- xml约束之schema
使用名称空间引入Schema : 通常需要在Xml文档中的根结点中使用schemaLocation属性来指定. <itcast:书架 xmlns:itcast="http://www. ...
- 转:Visual C++ sprintf()函数用法
将字串格式化命令.sprintf 是个变参函数,使用时经常出问题,而且只要出问题通常就是能导致程序崩溃的内存访 问错误,但好在由sprintf 误用导致的问题虽然严重,却很容易找出,无非就是那么几种情 ...
- (摘自ItPub)物理standby中switchover时switchover pending的解决办法
http://www.itpub.net/thread-1782245-1-1.html DataGuard一主一物理备,sid为primary和standby,现在要把primary切换成备库,st ...
- WebService实现文件上传下载
一:服务端:一个普通java web工程 package com.wzh.file; import com.sun.xml.ws.developer.StreamingAttachment; impo ...