传送门

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

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

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

首先

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

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

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

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

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

那么现在每个点的入度和出度之差都是偶数,我们把它除以二,设为$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. Photoshop中比较实用的小技巧

    Photoshop是目前最流行的图片处理软件软件之一.能够说,只要接触图片处理,就要和它打交道.Photoshop的强大功能和众多的优点不用多说.用photoshop做一些漂亮的图片,或对照片进行简单 ...

  2. Jmeter参数化HTTP request中Send Files With The Request的文件路径和文件名

  3. wcf服务契约的重载

    a. 服务端 .服务端 契约用OperationContract的Name实现重载 using System; using System.Collections.Generic; using Syst ...

  4. Response.Redirect原理图解

  5. li.active2有加强重要性的效果。

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. msys2 显示git branch

    在.bashrc或.bash_profile中添加以下内容 function parse_git_branch () { git branch 2> /dev/null | sed -e '/^ ...

  7. 库函数方式文件编程----fopen

    使用fopen等文件访问库函数编写应用程序,该应用程序实现文件的复制功能. 1.打开文件---fopen 函数功能:打开文件 头文件:#include<stdio.h> 函数原型:FILE ...

  8. 2018.07.18 HAOI2009 逆序对数列(线性dp)

    传送门 目前只会n2" role="presentation" style="position: relative;">n2n2的dp" ...

  9. Django入门与实践-第26章:个性化工具(完结)

    http://127.0.0.1:8000/boards/1/topics/62/reply/ 我觉得只添加内置的个性化(humanize)包就会很不错. 它包含一组为数据添加“人性化(human t ...

  10. 在windows7下创建ftp服务站点

    1.开始->控制面板->程序(点击“卸载程序”)->启动或关闭windows功能->Internet Information Services(Internet信息服务)-&g ...