BZOJ 2095 [POI2010]Bridges (最大流、欧拉回路)
洛谷上有这题,但是输出方案缺SPJ。。(而且我也懒得输出方案了)
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2095
题解: 首先判掉度数有奇数的特殊情况,一眼能看出来二分答案(二分下界要设成每条边较小权值的最大值),然后转化成:
给定一张图,有些边有方向,有些边无方向,问是否能给无向边定向使得所有边形成欧拉回路。
看着这个完全没觉得这像网络流啊……
好吧只要想到用网络流来做就非常简单了
考虑欧拉回路不就是每个点入度等于出度?现在入度不等于出度对吧?那我们考虑“入度等于出度”这个条件像什么?像流量平衡对吧。在网络流中每个点流入的流量等于流出的流量。
那么我们的目标是对于每个点都要求其入度出度相等均为\(\frac{du[i]}{2}\) (\(du[i]\)为\(i\)的度数,\(dui[i],duo[i]\)分别为入度出度)
现在我们已有的有向边入度比出度多\(dui[i]-duo[i]\), 那么它在无向边定向之后就要出度比入度多\(dui[i]-duo[i]\).
所以如果不加任何改动拿无向边跑最大流是出度等于入度,那么从\(S\)连一条\(dui[i]-duo[i]\)的边跑最大流就相当于出度比入度多\(dui[i]-duo[i]\)了。同理,如果出度比入度多,这条边就要连向T,权值为差的绝对值。
判断是否满流即可。
时间复杂度\(O(MaxFlow(n,m)\times \log W)\) (\(W\)为权值)
UPD: 为啥网上题解和我都不一样??我的做法是错的吗??求教
网上的题解都是: 对于无向边先随便定个向,然后加这条边的反向边边权为\(1\),对于每个点与\(S\)或者\(T\)连的边权是出入度之差除以\(2\), 因为每反向一条边相当于入度\(+1\)出度\(-1\), 对差的影响是\(2\).
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1002;
const int M = 8000;
const int INF = 1e7;
namespace MaxFlow
{
struct Edge
{
int v,w,nxt,rev;
} e[(M<<1)+3];
int n,en,s,t;
int dep[N+3];
int que[N+3];
int fe[N+3];
int te[N+3];
void clear()
{
for(int i=1; i<=n; i++) fe[i] = te[i] = 0;
for(int i=1; i<=en; i++) e[i].v = e[i].w = e[i].nxt = e[i].rev = 0;
n = en = s = t = 0;
}
void addedge(int u,int v,int w)
{
en++; e[en].v = v; e[en].w = w;
e[en].nxt = fe[u]; fe[u] = en; e[en].rev = en+1;
en++; e[en].v = u; e[en].w = 0;
e[en].nxt = fe[v]; fe[v] = en; e[en].rev = en-1;
}
bool bfs()
{
for(int i=1; i<=n; i++) dep[i] = 0;
int head = 1,tail = 1; que[tail] = s; dep[s] = 1;
while(head<=tail)
{
int u = que[head]; head++;
for(int i=fe[u]; i; i=e[i].nxt)
{
if(dep[e[i].v]==0 && e[i].w>0)
{
dep[e[i].v] = dep[u]+1;
tail++; que[tail] = e[i].v;
}
}
}
return dep[t]!=0;
}
int dfs(int u,int cur)
{
if(u==t) {return cur;}
int rst = cur;
for(int i=te[u]; i; i=e[i].nxt)
{
if(dep[e[i].v]==dep[u]+1 && e[i].w>0 && rst>0)
{
int flow = dfs(e[i].v,min(rst,e[i].w));
if(flow>0)
{
rst -= flow; e[i].w -= flow; e[e[i].rev].w += flow;
if(e[i].w>0) te[u] = i;
if(rst==0) {return cur;}
}
}
}
return cur-rst;
}
int dinic(int _n,int _s,int _t)
{
n = _n,s = _s,t = _t;
int ret = 0;
while(bfs())
{
for(int i=1; i<=n; i++) te[i] = fe[i];
ret += dfs(s,INF);
}
return ret;
}
}
using MaxFlow::addedge;
using MaxFlow::dinic;
struct AEdge
{
int u,v,w1,w2;
} ae[M+3];
int dui[N+3],duo[N+3],du[N+3];
int n,m;
void clear()
{
for(int i=1; i<=n; i++) dui[i] = duo[i] = 0;
MaxFlow::clear();
}
int main()
{
scanf("%d%d",&n,&m); int left = 0,right = 0;
for(int i=1; i<=m; i++)
{
scanf("%d%d%d%d",&ae[i].u,&ae[i].v,&ae[i].w1,&ae[i].w2);
left = max(left,min(ae[i].w1,ae[i].w2));
right = max(right,max(ae[i].w1,ae[i].w2));
du[ae[i].u]++; du[ae[i].v]++;
}
for(int i=1; i<=n; i++)
{
if(du[i]&1) {printf("NIE"); return 0;}
}
while(left<right)
{
int mid = left+((right-left)>>1);
int std = 0;
for(int i=1; i<=m; i++)
{
if(ae[i].w1<=mid && ae[i].w2<=mid)
{
addedge(ae[i].u+2,ae[i].v+2,1);
addedge(ae[i].v+2,ae[i].u+2,1);
}
else if(ae[i].w1<=mid)
{
duo[ae[i].u]++; dui[ae[i].v]++;
}
else if(ae[i].w2<=mid)
{
duo[ae[i].v]++; dui[ae[i].u]++;
}
}
for(int i=1; i<=n; i++)
{
if(dui[i]>duo[i])
{
addedge(i+2,2,dui[i]-duo[i]);
std += dui[i]-duo[i];
}
else if(duo[i]>dui[i])
{
addedge(1,i+2,duo[i]-dui[i]);
}
}
int ans = dinic(n+2,1,2);
if(ans==std) {right = mid;}
else {left = mid+1;}
clear();
}
printf("%d\n",right);
return 0;
}
BZOJ 2095 [POI2010]Bridges (最大流、欧拉回路)的更多相关文章
- bzoj 2095: [Poi2010]Bridges [混合图欧拉回路]
2095: [Poi2010]Bridges 二分答案,混合图欧拉路判定 一开始想了一个上下界网络流模型,然后发现不用上下界网络流也可以 对于无向边,强制从\(u \rightarrow v\),计算 ...
- BZOJ.2095.[POI2010]Bridges(最大流ISAP 二分 欧拉回路)
题目链接 最小化最大的一条边,二分答案.然后就变成了给一张无向图定向使其为欧拉回路 二分答案后对于一个位置的两条边可能都保留,即双向边,需要给它定向:可能只保留小的一条,即单向边,不需考虑 如何给它定 ...
- BZOJ 2095: [Poi2010]Bridges
2095: [Poi2010]Bridges Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 869 Solved: 299[Submit][Stat ...
- bzoj 2095 [Poi2010]Bridges 判断欧拉维护,最大流+二分
[Poi2010]Bridges Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1448 Solved: 510[Submit][Status][D ...
- BZOJ 2095 [Poi2010]Bridges (二分+最大流判断混合图的欧拉回路)
题面 nnn个点,mmm条双向边(正向与反向权值不同),求经过最大边权最小的欧拉回路的权值 分析 见 commonc大佬博客 精髓就是通过最大流调整无向边的方向使得所有点的入度等于出度 CODE #i ...
- bzoj 2095: [Poi2010]Bridges(二分法+混合图的欧拉回路)
[题意] 给定n点m边的无向图,对于边u,v,从u到v边权为c,从v到u的边权为d,问能够经过每条边一次且仅一次,且最大权值最小的欧拉回路. [思路] 二分答案mid,然后切断权值大于mid的边,原图 ...
- 【刷题】BZOJ 2095 [Poi2010]Bridges
Description YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛可以到另外任意一个小岛.现在YYD想骑单车从小岛1 ...
- [BZOJ2095][Poi2010]Bridges 最大流(混合图欧拉回路)
2095: [Poi2010]Bridges Time Limit: 10 Sec Memory Limit: 259 MB Description YYD为了减肥,他来到了瘦海,这是一个巨大的海, ...
- [Poi2010]Bridges 最大流+二分答案 判定混合图欧拉回路
https://darkbzoj.cf/problem/2095 bzoj 相同的题挂了,这个oj可以写. 题目就是要我们找一条欧拉回路(每个桥经过一次就好,不管方向),使得这条回路上权值最大的尽量小 ...
随机推荐
- 云服务器装teamviewer
[int32] EulaAccepted = 1 [int32] EulaAcceptedRevision = 6
- E2017E0605-hm
carbon copy 抄送, 抄写与送达 blind carbon copy 密送 blind adj. 失明的; 盲目的,轻率的; contact n. 接触; 触点 v 联系,接触; ...
- 为什么JavaWeb项目要分层
首先让我们坐着时光机回到n年前的web开发.那个时候最早都是静态的html页面,后来有了数据库,有了所谓的动态页面,然后程序猿在编码的时候,会把所有的代码都写在页面上,包括数据库连接,包括事务控制,接 ...
- [Swift]经典解题思路:联合查找Union Find
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- linux C编程 gdb的使用
linux C编程 gdb的使用 通常来说,gdb是linux在安装时自带的,在命令行键入"gdb"字符并按回车键会启动gdb调试环境. 1.gdb的基本命令 命令 说明 file ...
- [转]ASP.NET MVC HtmlHelper扩展之Calendar日期时间选择
本文转自:http://blog.bossma.cn/asp_net_mvc/asp-net-mvc-htmlhelper-calendar-datetime-select/ 这里我们扩展HtmlHe ...
- springboot与dubbo整合遇到的坑
整合环境: dubbo 2.6.2 springboot 2.1.5 遇到的问题:服务一直无法注册到zookeeper注册中心 项目结构: 使用application.properties文件: 配置 ...
- 手机页面操作栏的创建及WebFont的使用
一.手机界面底部操作栏的创建. <style> .opers{ position:absolute; bottom:0px; left:0px; right:0px; height:3re ...
- 使用SpringMvc的一个注意事项
在Intelij Idea下,如果在新建项目时使用了自带的模板,那么自动生成的web.xml里的DispatcherServlet配置节点默认的servlet-mapping是这样的: 而习惯上,我们 ...
- HDU_1561_The more, The Better_树型dp
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561 The more, The Better Time Limit: 6000/2000 MS (J ...