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可以写. 题目就是要我们找一条欧拉回路(每个桥经过一次就好,不管方向),使得这条回路上权值最大的尽量小 ...
随机推荐
- P1266 速度限制(分层图spfa)
P1266 速度限制 题目描述 在这个繁忙的社会中,我们往往不再去选择最短的道路,而是选择最快的路线.开车时每条道路的限速成为最关键的问题.不幸的是,有一些限速的标志丢失了,因此你无法得知应该开多快. ...
- js 上传头像
css .con4{width: 230px;height: auto;overflow: hidden;margin: 20px auto;color: #FFFFFF;} .con4 .btn{w ...
- 微信小程序获取自定义属性值
写小程序的时候用到了自定义属性,特地来记录一下 特别是这个坑,必须得说一说 wxml <view class='box' bindtap='getValue'> <view clas ...
- sql server 大数据处理
对SQL Server数据表进行分区的过程分为三个步骤: 1)建立分区函数 2)建立分区方案 3)对表格进行分区 第一个步骤:建立分区函数 分区函数定义[u]how[/u],即你想要SQL Serve ...
- 二分搜索 POJ 1064 Cable master
题目传送门 /* 题意:n条绳子问切割k条长度相等的最长长度 二分搜索:搜索长度,判断能否有k条长度相等的绳子 */ #include <cstdio> #include <algo ...
- 初识mybatis之入门案例
我也是自学了一下,在idea中基于maven的mybatis的配置.有什么不对的地方,请指正,谢谢. 1.1咋们先来配置测试一下,配置mybatis的图解: 1.2 pom.xml需要mybatis的 ...
- Sublime——基本操作
基本安装 程序下载地址:https://www.sublimetext.com/ package control安装 View -> Show Console打开控制台或者用快捷键ctrl+~打 ...
- Java 基础入门随笔(9) JavaSE版——文档注释
上节中写了一些static变量以及静态的方法的定义使用以及与非静态的差别,这节补充下: 如果在一个类中所有方法都为静态的,且无成员变量,这时候需要对对应的类进行限制该类无法创建对象,具体操作如下: p ...
- Flask框架 之第一个Flask程序
from flask import Flask # 创建flask应用对象 # __name__ 代表当前模块名称 # flask以当前目录为总目录,static目录为静态目录,templates为模 ...
- arx 插入图片
#include <ShLwApi.h> #pragma comment(lib, "ShLwApi.lib") //插入影像图 Acad::ErrorStatus i ...