2095: [Poi2010]Bridges

Time Limit: 10 Sec  Memory Limit: 259 MB

Description

YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛可以到另外任意一个小岛。现在YYD想骑单车从小岛1出发,骑过每一座桥,到达每一个小岛,然后回到小岛1。霸中同学为了让YYD减肥成功,召唤了大风,由于是海上,风变得十分大,经过每一座桥都有不可避免的风阻碍YYD,YYD十分ddt,于是用泡芙贿赂了你,希望你能帮他找出一条承受的最大风力最小的路线。

Input

输入:第一行为两个用空格隔开的整数n(2<=n<=1000),m(1<=m<=2000),接下来读入m行由空格隔开的4个整数a,b(1<=a,b<=n,a<>b),c,d(1<=c,d<=1000),表示第i+1行第i座桥连接小岛a和b,从a到b承受的风力为c,从b到a承受的风力为d。

Output

输出:如果无法完成减肥计划,则输出NIE,否则第一行输出承受风力的最大值(要使它最小)

Sample Input

4 4
1 2 2 4
2 3 3 4
3 4 4 4
4 1 5 4

Sample Output

4

HINT

注意:通过桥为欧拉回路
 
题解:注意到“最大值最小”这一关键词,不难转化为想到二分答案判合法性问题。
那么我们接下来要判断的就是“混合图是否存在欧拉回路”这一问题。
我们考虑先给无向边规定一个方向,但是在这种定义下,得到的图未必是一个欧拉图,即有的点入度大于出度,有的点出度大于入度。
接下来我们考虑给已经定向的无向边“反向”。
设i点入度与出度的差值为delta[i],那么对于每个点,delta[i]显然一定是偶数,因为连着它的一条边反向就会造成±2的改变;
那么我们要做到工作就是“反转”某些边,使得delta全为0为了实现目的,我们:
从源点向入度大于出度的点连流量为入度减出度/2的边,从入度小于出度向汇点的点连流量为出度减入度/2的边;
如果这样的边能够跑满,那么这个点就得到了完全的调整。
对一条无向边,连这条边的方向反向,流量为1的边,表示将这条边反向,两个点的入度与出度得到调整;
对这个网络求最大流就调整了尽可能多的无向边,源点和汇点所连边的流量都跑满时,
所有需要调整的边都被调整,出现了欧拉回路。
所以我们一开始记录一下与源点相连的边的流量和sum,再跑一边dinic/ISAP看是否满流即可。
代码实现:
 #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=,M=,inf=0x7fffffff;
struct edge{int zhong,next,flow;};
int a[M],b[M],c[M],d[M],delta[N],n,sum,m;
struct NetWork_Flow
{
edge s[M<<];
int S,T,e,adj[N],cur[N];
int dist[N],hd,tl,q[N],cnt[N];
inline void add(int qi,int zhong,int flow)
{s[++e].zhong=zhong,s[e].next=adj[qi],adj[qi]=e,s[e].flow=flow;}
inline void bfs()
{
memset(cnt,,sizeof(cnt)),memset(dist,,sizeof(dist));
hd=,tl=,dist[T]=,q[++tl]=T;
register int i,x;
while(hd<=tl)
for(x=q[hd++],++cnt[dist[x]],i=adj[x];i;i=s[i].next)
if(s[i^].flow&&!dist[s[i].zhong])
dist[s[i].zhong]=dist[x]+,q[++tl]=s[i].zhong;
}
inline int Shoot(int rt,int maxf)
{
if(rt==T||!maxf)return maxf;
register int i,x,u,f,ret=;
for(i=cur[rt];i;i=s[i].next)
if(dist[s[i].zhong]+==dist[rt])
{
f=Shoot(s[i].zhong,min(maxf,s[i].flow));
ret+=f,maxf-=f,s[i].flow-=f,s[i^].flow+=f;
if(!maxf)return ret;
}
if(!(--cnt[dist[rt]]))dist[S]=T+;
++cnt[++dist[rt]],cur[rt]=adj[rt];
return ret;
}
inline int ISAP()
{
register int i;
memcpy(cur,adj,sizeof(adj));
int maxf=;bfs();
while(dist[S]<=T+)maxf+=Shoot(S,inf);
return maxf;
}
inline void build(int val)
{
register int i;
e=,sum=,memset(adj,,sizeof(adj));
memset(delta,,sizeof(delta));
for(i=;i<=m;++i)
{
if(c[i]<=val)--delta[a[i]],++delta[b[i]];
if(d[i]<=val)
add(b[i],a[i],),add(a[i],b[i],);
}
for(i=;i<=n;++i)
if(delta[i]>)sum+=delta[i]/,add(S,i,delta[i]/),add(i,S,);
else add(i,T,-delta[i]/),add(T,i,);
}
inline bool check(int val)
{
register int i;
build(val);
for(i=;i<=n;++i)
if(delta[i]&)return ;
return ISAP()==sum;
}
}G;
int main()
{
scanf("%d%d",&n,&m);
G.S=n+,G.T=n+;
register int i,j;
int l=,r=,mi,ans=inf;
for(i=;i<=m;++i)
{
scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
if(c[i]>d[i])swap(c[i],d[i]),swap(a[i],b[i]);
l=min(l,c[i]),r=max(r,d[i]);
}
while(l<=r)
{
mi=l+r>>;
if(G.check(mi))r=mi-,ans=mi;
else l=mi+;
}
if(ans==inf)puts("NIE");
else printf("%d\n",ans);
}

[BZOJ2095][Poi2010]Bridges 最大流(混合图欧拉回路)的更多相关文章

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

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

  2. 【BZOJ-2095】Bridge 最大流 + 混合图欧拉回路 + 二分

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

  3. bzoj2095: [Poi2010]Bridges(二分+混合图求欧拉回路)

    传送门 这篇题解讲的真吼->这里 首先我们可以二分一个答案,然后把所有权值小于这个答案的都加入图中 那么问题就转化为一张混合图(既有有向边又有无向边)中是否存在欧拉回路 首先 无向图存在欧拉回路 ...

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

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

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

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

  6. BZOJ.2095.[POI2010]Bridges(最大流ISAP 二分 欧拉回路)

    题目链接 最小化最大的一条边,二分答案.然后就变成了给一张无向图定向使其为欧拉回路 二分答案后对于一个位置的两条边可能都保留,即双向边,需要给它定向:可能只保留小的一条,即单向边,不需考虑 如何给它定 ...

  7. POJ 1637 - Sightseeing tour - [最大流解决混合图欧拉回路]

    嗯,这是我上一篇文章说的那本宝典的第二题,我只想说,真TM是本宝典……做的我又痛苦又激动……(我感觉ACM的日常尽在这张表情中了) 题目链接:http://poj.org/problem?id=163 ...

  8. POJ 1637 Sightseeing tour(混合图欧拉回路+最大流)

    http://poj.org/problem?id=1637 题意:给出n个点和m条边,这些边有些是单向边,有些是双向边,判断是否能构成欧拉回路. 思路: 构成有向图欧拉回路的要求是入度=出度,无向图 ...

  9. BZOJ2095 [Poi2010]Bridges

    首先二分答案...然后这张图变成了有一些有向边,有一些无向边 然后就是混合图欧拉回路的判断 我们知道如果是有向图,它存在欧拉回路的等价条件是所有点的出度等于入度 对于混合图...先不管有向边,把无向边 ...

随机推荐

  1. 第四节:Windows系统安装时BIOS设置及注意

    BIOS系统 BIOS是英文"Basic Input Output System"的缩略词,直译过来后中文名称就是"基本输入输出系统".在IBM PC兼容系统上 ...

  2. RabbitMQ入门:总结

    随着上一篇博文的发布,RabbitMQ的基础内容我也学习完了,RabbitMQ入门系列的博客跟着收官了,以后有机会的话再写一些在实战中的应用分享,多谢大家一直以来的支持和认可. RabbitMQ入门系 ...

  3. NO--16 vue之父子组件传值

    先创建项目并运行 vue init webpack-simple templatecd templatenpm inpm run dev 一.子组件访问父组件的数据 方式一 :子组件直接访问父组件的数 ...

  4. 使用Zabbix的SNMP trap监控类型监控设备的一个例子

    本文以监控绿盟设备为例. 1.登录被监控的设备的管理系统,配置snmptrap地址指向zabbix服务器或代理服务器. snmptrap地址也叫陷阱. 2.验证是否能在zabbix服务器或代理服务器上 ...

  5. 温习DL之一:梯度的概念

    1.梯度的概念 梯度是一个矢量,表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向变化最快. 在微积分里面,对多元函数的参数求∂偏导数,把求得的各个参数的偏导数以向量的形式写 ...

  6. Cocos2dx源码赏析(3)之事件分发

    Cocos2dx源码赏析(3)之事件分发 这篇,继续从源码的角度赏析下Cocos2dx引擎的另一模块事件分发处理机制.引擎的版本是3.14.同时,也是学习总结的过程,希望通过这种方式来加深对Cocos ...

  7. Tomcat部署与使用

    Tomcat简介 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache.Sun和其他一些公司及个人共同开发 ...

  8. cal命令详解

    基础命令学习目录首页 原文链接:https://www.yiibai.com/linux/cal.html cal命令可以用来显示公历(阳历)日历.公历是现在国际通用的历法,又称格列历,通称阳历.“阳 ...

  9. shell--read命令

    read命令 -p(提示语句) -n(字符个数) -t(等待时间) -s(不回显) 1.基本读取read命令接收标准输入(键盘)的输入,或其他文件描述符的输入(后面在说).得到输入后,read命令将数 ...

  10. 查看jdk使用的是什么垃圾收集器

    一.方法一 打印虚拟机所有参数 [root@localhost ~]# java -XX:+PrintFlagsFinal -version | grep :    uintx InitialHeap ...