bzoj2095: [Poi2010]Bridges(二分+混合图求欧拉回路)
这篇题解讲的真吼->这里
首先我们可以二分一个答案,然后把所有权值小于这个答案的都加入图中
那么问题就转化为一张混合图(既有有向边又有无向边)中是否存在欧拉回路
首先
无向图存在欧拉回路,当且仅当图的所有顶点度数都为偶数且图连通。
有向图存在欧拉回路,当且仅当图的所有顶点入度等于出度且图连通。
那么我们怎么判断混合图的欧拉回路是否存在呢?
我们把无向边的边随便定向,然后计算每一个点的入度和出度。如果有某一个点的入度和出度之差是奇数,那么肯定不存在欧拉回路。
因为欧拉回路要求入度等于出度,也就是总度数为偶数,所以有奇数度点肯定不存在欧拉回路
那么现在每个点的入度和出度之差都是偶数,我们把它除以二,设为$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(二分+混合图求欧拉回路)的更多相关文章
- [BZOJ2095][Poi2010]Bridges 二分+网络流
2095: [Poi2010]Bridges Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1187 Solved: 408[Submit][Sta ...
- POJ 1637 混合图求欧拉回路 最大流实现
前面讲过了无向图,有向图求欧拉回路,欧拉通路的做法.可以直接根据度数来判断,当然前提是这是一个连通图. 这道题既有无向边,又有有向边,然后求欧拉回路. 采用的方法是最大流. 具体处理方法. 首先,我们 ...
- BZOJ2095 POI2010 Bridges 【二分+混合图欧拉回路】
BZOJ2095 POI2010 Bridges Description YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛 ...
- BZOJ2095:[POI2010]Bridges(最大流,欧拉图)
Description YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛可以到另外任意一个小岛.现在YYD想骑单车从小岛1 ...
- bzoj千题计划228:bzoj2095: [Poi2010]Bridges
http://www.lydsy.com/JudgeOnline/problem.php?id=2095 二分答案,判断是否存在混合图的欧拉回路 如果只有一个方向的风力<=mid,这条边就是单向 ...
- [POJ1637]混合图的欧拉回路判定|网络流
混合图的欧拉回路判定 上一篇正好分别讲了有向图和无向图的欧拉回路判定方法 如果遇上了混合图要怎么做呢? 首先我们思考有向图的判定方法:所有点的出度=入度 我们可以先为无向边任意定一个向,算出此时所有顶 ...
- 紫书 例题 11-13 UVa 10735(混合图的欧拉回路)(最大流)
这道题写了两个多小时-- 首先讲一下怎么建模 我们的目的是让所有点的出度等于入度 那么我们可以把点分为两部分, 一部分出度大于入度, 一部分入度大于出度 那么显然, 按照书里的思路,将边方向后,就相当 ...
- [BZOJ2095][Poi2010]Bridges 最大流(混合图欧拉回路)
2095: [Poi2010]Bridges Time Limit: 10 Sec Memory Limit: 259 MB Description YYD为了减肥,他来到了瘦海,这是一个巨大的海, ...
- bzoj 2095: [Poi2010]Bridges(二分法+混合图的欧拉回路)
[题意] 给定n点m边的无向图,对于边u,v,从u到v边权为c,从v到u的边权为d,问能够经过每条边一次且仅一次,且最大权值最小的欧拉回路. [思路] 二分答案mid,然后切断权值大于mid的边,原图 ...
随机推荐
- 开发中常遇到的Python陷阱和注意点-乾颐堂
最近使用Python的过程中遇到了一些坑,例如用datetime.datetime.now()这个可变对象作为函数的默认参数,模块循环依赖等等. 在此记录一下,方便以后查询和补充. 避免可变对象作为默 ...
- asp.net core 视图组件化
视图组件可以通过partial view或viewcomponent实现 partialview https://docs.microsoft.com/zh-cn/aspnet/core/mvc/vi ...
- 482. License Key Formatting
static int wing=[]() { std::ios::sync_with_stdio(false); cin.tie(NULL); ; }(); class Solution { publ ...
- 2018.09.26 bzoj5218: [Lydsy2017省队十连测]友好城市(回滚莫队)
传送门 比较简单的一道回滚莫队吧. 每次询问用bitset优化kosaraju统计答案. 就是有点难调. 然后向dzyo学长学习了回滚莫队的一种简洁的实现方式,就是直接建立一个sqrt(m)∗sqrt ...
- 2018.08.02 洛谷P3355 骑士共存问题(最小割)
传送门 这题让我联想到一道叫做方格取数问题的题,如果想使摆的更多,就要使不能摆的更少,因此根据骑士的限制条件建图,求出至少有多少骑士不能摆,减一减就行了. 代码: #include<bits/s ...
- hdu-1179(匈牙利算法)
题目链接: 思路:找n个巫师和m个魔棒匹配的问题,匈牙利算法模板 匈牙利算法:https://blog.csdn.net/sunny_hun/article/details/80627351 #inc ...
- HDU 2393 Higher Math (判断直角三角形)
题意:给定三个边,判断是不是直角三角形. 析:水题,勾股定理... 代码如下: #include <iostream> #include <cstdio> #include & ...
- js继承——扩展Object方式实现继承
function Parent(name,sex){ this.name = name; this.sex = sex; this.sayName = function(){ console.log( ...
- 文件读取ndarry 等价于DataFrame的操作
LD=loadDatas() userMat=LD.makeRatingMatWithoutUserID() print(type(userMat)) userRatingMat=pd.DataFra ...
- 20155211 2016-2017-2 《Java程序设计》第七周学习总结
20155211 2016-2017-2 <Java程序设计>第七周学习总结 教材学习内容总结 第十二章 Lambda Lambda表达式中this的参考对象以及toString()的接受 ...