题目链接

最小化最大的一条边,二分答案。然后就变成了给一张无向图定向使其为欧拉回路

二分答案后对于一个位置的两条边可能都保留,即双向边,需要给它定向;可能只保留小的一条,即单向边,不需考虑

如何给它定向呢,或者说怎么形成欧拉回路呢

形成欧拉回路的充要条件:弱连通图;每个点出度=入度

记点i的度数 dgr[i]=out[i]-in[i]

对于一条方向确定的边(u,v),如果改变它的方向,会使dgr[u]-=2,dgr[v]+=2,也就是说u的2度数分配给了v

对于in[x]!=out[x]的点都要通过改变某些边方向满足in[x]==out[x]

最大流,构图就不说了

刚开始时对一条无向边保留一次它反向的机会,随便定个向,就权值小的吧

注意度数是每次u,v都改变1的,建边时dgr/2

如果有某个点出入度之差为奇数,则不可能形成欧拉回路

ISAP初始度数的最大值要是des+1...

Dinic无限TLE原来是M小了...mmp..

ISAP无限WA还是找不出原因...

Dinic:

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define gc() getchar()
const int N=1005,M=2005+2*N,INF=1e9; int n,m,src,des,dgr[N],u[M],v[M],A[M],B[M];
int Enum,cur[N],H[N],nxt[M<<1],fr[M<<1],to[M<<1],cap[M<<1],lev[N],q[N],path[N],num[N]; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
inline void AddEdge(int u,int v,int w)
{
to[++Enum]=v, fr[Enum]=u, nxt[Enum]=H[u], cap[Enum]=w, H[u]=Enum;
to[++Enum]=u, fr[Enum]=v, nxt[Enum]=H[v], cap[Enum]=0, H[v]=Enum;
}
int Rebuild(int x)
{
Enum=1, memset(H,0,sizeof H), memset(dgr,0,sizeof dgr);
for(int i=1;i<=m;++i)
{
if(A[i]<=x) ++dgr[u[i]],--dgr[v[i]];//选择作为单向边或是选中这个方向 需改变的度数就是1!
if(B[i]<=x) AddEdge(u[i],v[i],1);//由u->v可以给出1度数
}
int tot=0;
for(int i=1;i<=n;++i)
if(dgr[i]>0) AddEdge(src,i,dgr[i]>>1),tot+=dgr[i]>>1;
else if(dgr[i]<0) AddEdge(i,des,-dgr[i]>>1);
return tot;//返回不平衡的度数
}
bool BFS2()
{
for(int i=0;i<=des;++i) lev[i]=0,cur[i]=H[i];
lev[src]=1, q[0]=src;
int h=0,t=1;
while(h<t)
{
int x=q[h++];
for(int i=H[x];i;i=nxt[i])
if(!lev[to[i]] && cap[i])
{
lev[to[i]]=lev[x]+1, q[t++]=to[i];
if(to[i]==des) return 1;
}
}
return 0;
}
int Dinic(int u,int flow)
{
if(u==des) return flow;
int used=0;
for(int &i=cur[u];i;i=nxt[i])
if(lev[to[i]]==lev[u]+1 && cap[i])
{
int delta=Dinic(to[i],std::min(cap[i],flow-used));
if(delta)
{
cap[i]-=delta, cap[i^1]+=delta, used+=delta;
if(used==flow) return flow;
}
}
lev[u]=0;
return used;
}
int MF()
{
for(int i=1;i<=n;++i)
if(dgr[i]&1) return -1;//如果有度数为1的点,则不可能形成欧拉回路
int tot=0;
while(BFS2()) tot+=Dinic(src,INF);
return tot;
// return ISAP();
} int main()
{
n=read(),m=read(),src=0,des=n+1;
int mx=0,mn=INF;
for(int i=1;i<=m;++i)
{
u[i]=read(),v[i]=read(),A[i]=read(),B[i]=read();
if(A[i]>B[i]) std::swap(A[i],B[i]),std::swap(u[i],v[i]);//用A做较小的边,单向边也肯定是较小的边啊
mn=std::min(mn,A[i]), mx=std::max(mx,B[i]);
}
int l=mn,r=mx+1,mid;
while(l<r)
{
mid=l+r>>1;
if(Rebuild(mid)==MF()) r=mid;
else l=mid+1;
}
if(l==mx+1) printf("NIE");
else printf("%d",l); return 0;
}

ISAP(WA):

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define gc() getchar()
const int N=1005,M=2005+2*N,INF=1e9; int n,m,src,des,dgr[N],u[M],v[M],A[M],B[M];
int Enum,cur[N],H[N],nxt[M<<1],fr[M<<1],to[M<<1],cap[M<<1],lev[N],q[N],path[N],num[N]; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
inline void AddEdge(int u,int v,int w)
{
to[++Enum]=v, fr[Enum]=u, nxt[Enum]=H[u], cap[Enum]=w, H[u]=Enum;
to[++Enum]=u, fr[Enum]=v, nxt[Enum]=H[v], cap[Enum]=0, H[v]=Enum;
}
int Rebuild(int x)
{
Enum=1, memset(H,0,sizeof H), memset(dgr,0,sizeof dgr);
for(int i=1;i<=m;++i)
{
if(A[i]<=x) ++dgr[u[i]],--dgr[v[i]];//选择作为单向边或是选中这个方向 需改变的度数就是1
if(B[i]<=x) AddEdge(u[i],v[i],1);//由u->v可以给出1度数
}
int tot=0;
for(int i=1;i<=n;++i)
if(dgr[i]>0) AddEdge(src,i,dgr[i]>>1),tot+=dgr[i]>>1;
else if(dgr[i]<0) AddEdge(i,des,-dgr[i]>>1);
return tot;//返回不平衡的度数
}
bool BFS()
{
for(int i=src;i<=des;++i) lev[i]=des+1,cur[i]=H[i];
q[0]=des, lev[des]=0;
int h=0,t=1;
while(h<t)
{
int x=q[h++];
for(int i=H[x];i;i=nxt[i])
if(lev[to[i]]==des+1 && cap[i^1])//i^1
lev[to[i]]=lev[x]+1, q[t++]=to[i];
}
return lev[src]<=des;
}
int Augment()
{
int mn=INF;
for(int i=des;i!=src;i=fr[path[i]])
mn=std::min(mn,cap[path[i]]);
for(int i=des;i!=src;i=fr[path[i]])
cap[path[i]]-=mn, cap[path[i]^1]+=mn;
return mn;
}
int ISAP()
{
if(!BFS()) return -1;
memset(num,0,sizeof num);//mmp
for(int i=src;i<=des;++i) ++num[lev[i]];
int x=src,flow=0;
while(lev[src]<=des)
{
if(x==des) flow+=Augment(),x=src;
bool can=0;
for(int i=cur[x];i;i=nxt[i])
if(lev[to[i]]==lev[x]-1 && cap[i])
{
can=1, cur[x]=i, path[x=to[i]]=i;
break;
}
if(!can)
{
int mn=des;
for(int i=H[x];i;i=nxt[i])
if(cap[i]) mn=std::min(mn,lev[to[i]]);
if(!--num[lev[x]]) break;
++num[lev[x]=mn+1], cur[x]=H[x];
if(x!=src) x=fr[path[x]];
}
}
return flow;
}
int MF()
{
for(int i=1;i<=n;++i)
if(dgr[i]&1) return -1;//如果有度数为1的点,则不可能形成欧拉回路
return ISAP();
} int main()
{
n=read(),m=read(),src=0,des=n+1;
int mx=0,mn=INF;
for(int i=1;i<=m;++i)
{
u[i]=read(),v[i]=read(),A[i]=read(),B[i]=read();
if(A[i]>B[i]) std::swap(A[i],B[i]),std::swap(u[i],v[i]);//用A做较小的边,单向边也肯定是较小的边啊
mn=std::min(mn,A[i]), mx=std::max(mx,B[i]);
}
int l=mn,r=mx+1,mid;
while(l<r)
{
mid=l+r>>1;
if(Rebuild(mid)==MF()) r=mid;
else l=mid+1;
}
if(l==mx+1) printf("NIE");
else printf("%d",l); return 0;
}

BZOJ.2095.[POI2010]Bridges(最大流ISAP 二分 欧拉回路)的更多相关文章

  1. BZOJ 2095 [POI2010]Bridges (最大流、欧拉回路)

    洛谷上有这题,但是输出方案缺SPJ..(而且我也懒得输出方案了) 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2095 题解: 首先判 ...

  2. bzoj 2095: [Poi2010]Bridges [混合图欧拉回路]

    2095: [Poi2010]Bridges 二分答案,混合图欧拉路判定 一开始想了一个上下界网络流模型,然后发现不用上下界网络流也可以 对于无向边,强制从\(u \rightarrow v\),计算 ...

  3. BZOJ 2095: [Poi2010]Bridges

    2095: [Poi2010]Bridges Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 869  Solved: 299[Submit][Stat ...

  4. bzoj 2095 [Poi2010]Bridges 判断欧拉维护,最大流+二分

    [Poi2010]Bridges Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1448  Solved: 510[Submit][Status][D ...

  5. BZOJ 2095 [Poi2010]Bridges (二分+最大流判断混合图的欧拉回路)

    题面 nnn个点,mmm条双向边(正向与反向权值不同),求经过最大边权最小的欧拉回路的权值 分析 见 commonc大佬博客 精髓就是通过最大流调整无向边的方向使得所有点的入度等于出度 CODE #i ...

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

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

  7. 【刷题】BZOJ 2095 [Poi2010]Bridges

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

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

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

  9. [Poi2010]Bridges 最大流+二分答案 判定混合图欧拉回路

    https://darkbzoj.cf/problem/2095 bzoj 相同的题挂了,这个oj可以写. 题目就是要我们找一条欧拉回路(每个桥经过一次就好,不管方向),使得这条回路上权值最大的尽量小 ...

随机推荐

  1. ansible报错Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this

    安装和配置好ansible,执行命令时报错如下 [root@test01 ansible-install]# ansible test -m shell -a 'w' >> Using a ...

  2. JSON和JSONP详解

    什么是JSON JSON是一种基于文本的数据交换方式,或者叫做数据描述格式,你是否该选用他首先肯定要关注它所拥有的优点. JSON的优点: 1.基于纯文本,跨平台传递极其简单: 2.Javascrip ...

  3. cacti系列(一)之cacti的安装及配置监控mysql服务

    简介 Cacti是通过 snmpget来获取数据,使用 RRDtool绘画图形,而且你完全可以不需要了解RRDtool复杂的参数.它提供了非常强大的数据和用户管理功能,可以指定每一个用户能查看树状结构 ...

  4. 用命令打开本地tomcat服务器

    1.点击开始菜单,搜索cmd,默认第一个结果是cmd.exe, 鼠标右键用管理员权限打开(win7及以上版本系统) 启动命令是net start tomcat8 (我电脑是tomcat8,如果是tom ...

  5. PYTHON-匿名函数,递归与二分法,面向过程编程

    """匿名函数1 什么是匿名函数 def定义的是有名函数:特点是可以通过名字重复调用 def func(): #func=函数的内存地址 pass 匿名函数就是没有名字的 ...

  6. 改变input标签中placeholder显示的颜色

    ::-webkit-input-placeholder { /* WebKit browsers */ color: #A9A9A9; } :-moz-placeholder { /* Mozilla ...

  7. Quartz 定时邮件发送多个备份文件

    项目代码 pom.xml 文件Quartz 的包是整个项目不可缺少的 <properties> <!-- Spring的版本 --> <springframework.v ...

  8. MACE(2)-----模型编译

    作者:十岁的小男孩 QQ:929994365 无用 本文仅用于学习研究,非商业用途,欢迎大家指出错误一起学习,文章内容翻译自 MACE 官方手册,记录本人阅读与开发过程,力求不失原意,但推荐阅读原文. ...

  9. php实现概率性随机抽奖代码

    1.初始数据: 权重越大,抽取的几率越高 [奖品1, 权重 5], [ 奖品2, 权重6], [ 奖品3, 权重 7], [ 奖品4, 权重2] 2.处理步骤: 1)N = 5 + 6 + 7 + 2 ...

  10. python 全栈开发,Day124(MongoDB初识,增删改查操作,数据类型,$关键字以及$修改器,"$"的奇妙用法,Array Object 的特殊操作,选取跳过排序,客户端操作)

    一.MongoDB初识 什么是MongoDB MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言编写.旨在为 WEB 应用提供可扩展的高性能数据存储解决方案. MongoDB 是一个介 ...