传送门

这篇题解讲的真吼->这里

首先我们可以二分一个答案,然后把所有权值小于这个答案的都加入图中

那么问题就转化为一张混合图(既有有向边又有无向边)中是否存在欧拉回路

首先

无向图存在欧拉回路,当且仅当图的所有顶点度数都为偶数且图连通。

       有向图存在欧拉回路,当且仅当图的所有顶点入度等于出度且图连通。

那么我们怎么判断混合图的欧拉回路是否存在呢?

我们把无向边的边随便定向,然后计算每一个点的入度和出度。如果有某一个点的入度和出度之差是奇数,那么肯定不存在欧拉回路。

因为欧拉回路要求入度等于出度,也就是总度数为偶数,所以有奇数度点肯定不存在欧拉回路

那么现在每个点的入度和出度之差都是偶数,我们把它除以二,设为$x$,那么,对于每一个点,我们只要改变与它相连的$x$条边的方向改变,它就能保证入度等于出度。如果每个点都能这样,那么这张图就存在一个欧拉回路

那么我们该改变哪些边来让点的出度等于入度呢?首先,有向边不能改变,忽略。然后我们一开始不是把无向边定向了么?那我们就按照定的向构建网络,边长容量$1$。然后新建源点和汇点,如果入度大于出度,则将点向汇点连边,容量为$x$,如果出度大于入度,则将源点向该点连边,容量为$x$。然后我们只要跑一个最大流,看看能否使网络满流。若可以,则有解,否则无解

考虑为什么。我们把网络中每一条满流的边(也就是流量非0的边)反向,就能得到一个每点入度等于出度的欧拉图。因为这个网络满流,所以每一个入度大于出度的点都会有$x$条边进来,把这$x$条边反向就能使它入度等于出度。出度大于入度的点同理。那么,既没和源点连也没和汇点连的点怎么办呢?因为这样的点必定是入度等于出度的,那么在网络流过程中他们属于中间点,那么必定满足流量守恒,所以进来的流量和出去的流量是一样的,那么反向之后仍然保持平衡

解决了

 //minamoto
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,:;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,:;}
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
const int N=,M=;
int head[N],Next[M],ver[M],edge[M],tot;
int out[N],in[N],u[N],v[N],w1[N],w2[N],sum;
int dep[N],cur[N];
int n,m,s,t;
queue<int> q;
inline void add(int u,int v,int e){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;
ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=;
}
bool bfs(){
memset(dep,-,sizeof(dep));
while(!q.empty()) q.pop();
for(int i=s;i<=t;++i) cur[i]=head[i];
q.push(s),dep[s]=;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(dep[v]<&&edge[i]){
dep[v]=dep[u]+,q.push(v);
if(v==t) return true;
}
}
}
return false;
}
int dfs(int u,int limit){
if(u==t||!limit) return limit;
int flow=,f;
for(int i=cur[u];i;i=Next[i]){
int v=ver[i];cur[u]=i;
if(dep[v]==dep[u]+&&(f=dfs(v,min(limit,edge[i])))){
flow+=f,limit-=f;
edge[i]-=f,edge[i^]+=f;
if(!limit) break;
}
}
if(!flow) dep[u]=-;
return flow;
}
int dinic(){
int flow=;
while(bfs()) flow+=dfs(s,inf);
return flow;
}
bool check(int mid){
memset(head,,sizeof(head)),tot=;
memset(out,,sizeof(out));
memset(in,,sizeof(in));
sum=;
for(int i=;i<=m;++i){
if(w1[i]<=mid) ++out[u[i]],++in[v[i]];//有向边记入度和出度
if(w2[i]<=mid) add(u[i],v[i],);//无向边随便定个方向
}
for(int i=;i<=n;++i) if(abs(in[i]-out[i])&) return false;
for(int i=;i<=n;++i){
int x=in[i]-out[i];
sum+=x>?x>>:;
if(x>) add(i,t,x>>);
if(x<) add(s,i,(-x)>>);
}
return dinic()==sum;
}
int main(){
//freopen("testdata.in","r",stdin);
n=read(),m=read(),s=,t=n+;
int l=inf,r=-inf;
for(int i=;i<=m;++i){
u[i]=read(),v[i]=read(),w1[i]=read(),w2[i]=read();
if(w1[i]>w2[i]) swap(u[i],v[i]),swap(w1[i],w2[i]);
cmin(l,w1[i]),cmax(r,w2[i]);
}
while(l<=r){
int mid=l+r>>;
if(check(mid)) r=mid-;else l=mid+;
}
if(!check(l)) puts("NIE");else printf("%d\n",l);
return ;
}
?

bzoj2095: [Poi2010]Bridges(二分+混合图求欧拉回路)的更多相关文章

  1. [BZOJ2095][Poi2010]Bridges 二分+网络流

    2095: [Poi2010]Bridges Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1187  Solved: 408[Submit][Sta ...

  2. POJ 1637 混合图求欧拉回路 最大流实现

    前面讲过了无向图,有向图求欧拉回路,欧拉通路的做法.可以直接根据度数来判断,当然前提是这是一个连通图. 这道题既有无向边,又有有向边,然后求欧拉回路. 采用的方法是最大流. 具体处理方法. 首先,我们 ...

  3. BZOJ2095 POI2010 Bridges 【二分+混合图欧拉回路】

    BZOJ2095 POI2010 Bridges Description YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛 ...

  4. BZOJ2095:[POI2010]Bridges(最大流,欧拉图)

    Description YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛可以到另外任意一个小岛.现在YYD想骑单车从小岛1 ...

  5. bzoj千题计划228:bzoj2095: [Poi2010]Bridges

    http://www.lydsy.com/JudgeOnline/problem.php?id=2095 二分答案,判断是否存在混合图的欧拉回路 如果只有一个方向的风力<=mid,这条边就是单向 ...

  6. [POJ1637]混合图的欧拉回路判定|网络流

    混合图的欧拉回路判定 上一篇正好分别讲了有向图和无向图的欧拉回路判定方法 如果遇上了混合图要怎么做呢? 首先我们思考有向图的判定方法:所有点的出度=入度 我们可以先为无向边任意定一个向,算出此时所有顶 ...

  7. 紫书 例题 11-13 UVa 10735(混合图的欧拉回路)(最大流)

    这道题写了两个多小时-- 首先讲一下怎么建模 我们的目的是让所有点的出度等于入度 那么我们可以把点分为两部分, 一部分出度大于入度, 一部分入度大于出度 那么显然, 按照书里的思路,将边方向后,就相当 ...

  8. [BZOJ2095][Poi2010]Bridges 最大流(混合图欧拉回路)

    2095: [Poi2010]Bridges Time Limit: 10 Sec  Memory Limit: 259 MB Description YYD为了减肥,他来到了瘦海,这是一个巨大的海, ...

  9. bzoj 2095: [Poi2010]Bridges(二分法+混合图的欧拉回路)

    [题意] 给定n点m边的无向图,对于边u,v,从u到v边权为c,从v到u的边权为d,问能够经过每条边一次且仅一次,且最大权值最小的欧拉回路. [思路] 二分答案mid,然后切断权值大于mid的边,原图 ...

随机推荐

  1. jstl标签详解 (转载)

    JSLT标签库,是日常开发经常使用的,也是众多标签中性能最好的.把常用的内容,放在这里备份一份,随用随查.尽量做到不用查,就可以随手就可以写出来.这算是Java程序员的基本功吧,一定要扎实. JSTL ...

  2. Ubuntu部分命令的使用简介

    1.查看USB设备 lsusb #查看系统中的usb设备 lsusb –v  #查看详细的usb设备信息 2.ubuntu mount u盘 第一步:查看U盘信息 sudo fdisk -l 得到类似 ...

  3. Debian 采用 iso 镜像作为 apt 源

    1.将N个debian-506-amd64-DVD-N.iso存放于本地或其他媒介内,本例是放在本机/iso/目录下2.创建N个挂载点目录 如下: debian:~#mkdir –r /media/d ...

  4. 抽象 abstract 和 接口 interface。 java 的 堆 和 栈。 参数传递(基本类型和普通对象的区别)

    package com.test; import com.test.Pro; //protected 修饰的成员只能在本包中和 继承该类的方法中使用 public abstract class Tes ...

  5. part1:8-远程登录Linux

    Linux远程登录 Linux系统中是通过ssh服务实现的远程登录功能.默认ssh服务开启了22端口,而且在安装完成系统时,这个服务已经安装,并且是开机启动的.所以不需要额外配置就能直接远程登录Lin ...

  6. proc demo

    源文件test.pc #include <stdio.h> #include <string.h> #include <stdlib.h> #include &qu ...

  7. cubieboard安装小记

    1.1.使用ttl线 ttl线驱动程序:PL2303_Prolific_DriverInstaller_v1.7.0.exe(驱动精灵上下载) ttl终端:http://the.earth.li/~s ...

  8. mac安全与隐私只有两个选项,少了一个任何来源

    很多软件安装后就会出现,程序已损坏,请移到废纸篓的提示. 解决方法:在终端里输入:sudo spctl --master-disable 然后回车,然后输入密码,即可在安全选项中看到重新出现的允许任何 ...

  9. Centos记录所有用户登录和操作的详细日志

    1.起因 最近Linux服务器上一些文件呗篡改,想追查已经查不到记录了,所以得想个办法记录下所有用户的操作记录. 一般大家通常会采用history来记录,但是history有个缺陷就是默认是1000行 ...

  10. ORACLE 查看分区表分区大小

    SELECT *  FROM dba_segments t WHERE t.segment_name ='table_name'; pratition_name : 分区名 bytes : 分区大小( ...