HLPP算法 一种高效的网络最大流算法
#include <algorithm>
#include <cstdio>
#include <cctype>
#include <queue>
#define INF 0x3f3f3f3f
#define MAXN 10010
#define MAXM 300010
using namespace std;
int n, m, s, t, tot = ;
int beginx[MAXN], endx[MAXM], nxt[MAXM], res[MAXM];
inline void add_edge(int u, int v, int w)
{
nxt[++tot] = beginx[u], beginx[u] = tot, endx[tot] = v, res[tot] = w;
nxt[++tot] = beginx[v], beginx[v] = tot, endx[tot] = u, res[tot] = ;
}
struct PQ
{
int x,h;
PQ(int _x,int _h)
{
x = _x, h = _h;
}
bool operator < (const PQ &tar) const
{
return h < tar.h;
}
};
int gap[MAXN], d[MAXN], ans[MAXN];
inline bool push(int x, int y, int ptr)
{
int w = min(ans[x], res[ptr]);
res[ptr] -= w, res[ptr^] += w;
ans[x] -= w, ans[y] += w;
return w;
}
inline void Gap(int val)
{
for (int i = ; i <= n; ++i)
if(i != s && i != t && val < d[i] && d[i] <= n)
d[i] = n + ;
}
inline int HLPP()
{
priority_queue<PQ> pq;
d[s] = n, ans[s] = INF, pq.push(PQ(s, d[s]));
int u;
while(!pq.empty())
{
u = pq.top().x, pq.pop();
if(!ans[u]) continue;
for(int i = beginx[u], v = endx[i]; i; i = nxt[i], v = endx[i])
if((u == s || d[u] == d[v] + ) && push(u, v, i) && v != t && v != s)
pq.push(PQ(v, d[v]));
if (u != s && u != t && ans[u])
{
if(!(--gap[d[u]])) Gap(d[u]);
++gap[++d[u]];
pq.push(PQ(u, d[u]));
}
}
return ans[t];
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i = ; i <= m; i++)
{
int u,v,r;
scanf("%d%d%d",&u,&v,&r);
add_edge(u, v, r);
}
printf("%d", HLPP());
return ;
}
HLPP
主程序仅有35行,可能会TLE,需要卡卡常数。
暴露出的问题:
- priority_queue太慢,用pq比普通队列还慢。
- STL效率差到爆炸,明明是需要多次BFS,入队出队次数很多,然而效率低,没办法,卡死了。
#include <cstdio>
#include <cctype>
using namespace std;
#define MAXN 10005
#define MAXM 200010
#define INF 0x3f3f3f3f inline char get_char()
{
static char buf[], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, , , stdin), p1 == p2) ? EOF : *p1 ++;
}
inline int read()
{
register int num = ;
char c;
while (isspace(c = get_char()));
while (num = num * + c - , isdigit(c = get_char()));
return num;
}
inline void upmin(int &a, const int &b)
{
if(a > b) a = b;
} int beginx[MAXN], endx[MAXM], nxt[MAXM], res[MAXM]; struct Q
{
int s, t;
Q()
{
s = , t = ;
}
int q[MAXM];
inline bool empty()
{
return s > t;
}
inline int front()
{
return q[s++];
}
inline void push(int tar)
{
q[++t] = tar;
}
} mession; int main()
{
register int n = read(), m = read(), s = read(), t = read(), tot = ;
for(int i = ; i <= m; i++)
{
int u = read(), v = read(), c = read();
nxt[++tot] = beginx[u], beginx[u] = tot, endx[tot] = v, res[tot] = c;
nxt[++tot] = beginx[v], beginx[v] = tot, endx[tot] = u, res[tot] = ;
}
register int ar = s, r = INF, ans = ;
bool done;
int d[MAXN], num[MAXN], cur[MAXN], pre[MAXN];
mession.push(t);
d[t] = ;
register int u, v;
while(!mession.empty())
{
u = mession.front();
num[d[u]]++;
for(int i = beginx[u]; i; i = nxt[i])
{
v = endx[i];
if(!d[v] && res[i ^ ])
{
d[v] = d[u] + ;
mession.push(v);
}
}
}
for(int i = ; i <= n; i++) cur[i] = beginx[i];
while(d[s] != n + )
{
if(ar == t)
{
while(ar != s)
{
res[pre[ar]] -= r, res[pre[ar] ^ ] += r;
ar = endx[pre[ar] ^ ];
}
ans += r, r = INF;
}
done = false;
for(int &i = cur[ar]; i; i = nxt[i])
{
int v = endx[i];
if(res[i] && d[v] == d[ar] - )
{
done = true, pre[v] = i, ar = v;
upmin(r, res[i]);
break;
}
}
if(!done)
{
register int heig = n + ;
for(int i = beginx[ar]; i; i = nxt[i])
{
int v = endx[i];
if(res[i]) upmin(heig, d[v] + );
}
if(--num[d[ar]] == ) break;
cur[ar] = beginx[ar];
num[d[ar] = heig]++;
if(ar != s) ar = endx[pre[ar] ^ ];
}
}
printf("%d", ans);
return ;
}
HLPP算法 一种高效的网络最大流算法的更多相关文章
- 网络最大流算法—EK算法
前言 EK算法是求网络最大流的最基础的算法,也是比较好理解的一种算法,利用它可以解决绝大多数最大流问题. 但是受到时间复杂度的限制,这种算法常常有TLE的风险 思想 还记得我们在介绍最大流的时候提到的 ...
- 网络最大流算法—Dinic算法及优化
前置知识 网络最大流入门 前言 Dinic在信息学奥赛中是一种最常用的求网络最大流的算法. 它凭借着思路直观,代码难度小,性能优越等优势,深受广大oier青睐 思想 $Dinic$算法属于增广路算法. ...
- 网络最大流算法—最高标号预流推进HLPP
吐槽 这个算法.. 怎么说........ 学来也就是装装13吧.... 长得比EK丑 跑的比EK慢 写着比EK难 思想 大家先来猜一下这个算法的思想吧:joy: 看看人家的名字——最高标号预留推进 ...
- 算法9-5:最大流算法的Java代码
残留网络 在介绍最大流算法之前先介绍一下什么是残留网络.残余网络的概念有点类似于集合中的补集概念. 下图是残余网络的样例. 上面的网络是原始网络.以下的网络是计算出的残留网络.残留网络的作用就是用来描 ...
- [学习笔记] 网络最大流的HLPP算法
#define \(u\)的伴点集合 与\(u\)相隔一条边的且\(u\)能达到的点的集合 \(0x00~ {}~Preface\) \(HLPP(Highest~Label~Preflow~Push ...
- 使用JavaScript进行数组去重——一种高效的算法
最近比较忙,没时间更新博客,等忙完这阵子会整理一篇使用AngularJS构建一个中型的单页面应用(SPA)的文章,尽情期待!先占个坑. 数组去重的算法有很多种,以下是一种. 思路如下: 定义一个空的对 ...
- 神经网络训练中的Tricks之高效BP(反向传播算法)
神经网络训练中的Tricks之高效BP(反向传播算法) 神经网络训练中的Tricks之高效BP(反向传播算法) zouxy09@qq.com http://blog.csdn.net/zouxy09 ...
- 最大流算法-最高标号预流推进(HLPP)
昨天我们学习了ISAP算法,它属于增广路算法的大类.今天学习的算法是预流推进算法中很高效的一类--最高标号预流推进(HLPP). 预流推进 预流推进是一种很直观的网络流算法.如果给到一个网络流让你手算 ...
- larbin是一种开源的网络爬虫/网络蜘
larbin是一种开源的网络爬虫/网络蜘蛛,由法国的年轻人 Sébastien Ailleret独立开发.larbin目的是能够跟踪页面的url进行扩展的抓取,最后为搜索引擎提供广泛的数据来源.Lar ...
随机推荐
- HDU 4503
可以反过来求不是相同关系的小朋友.相当于染色问题吧. 对于A小朋友,它的T个朋友和另外的(N-1-T)个同学就可以组成一个这样的三角形.T*(N-1-T),由于一条非染色边被计算两次,所以除以2. # ...
- Libevent 学习笔记 (1)——Libevent 2.0安装与简单演示样例
今天開始学习Libevent . Libevent 是开源社区的一款高性能I/O框架库. 主要特点有: 1 跨平台. 2 统一事件源 3 线程安全 4 基于Reactor 今天主要进行了Libeven ...
- 欧几里得 & 拓展欧几里得算法 解说 (Euclid & Extend- Euclid Algorithm)
欧几里得& 拓展欧几里得(Euclid & Extend-Euclid) 欧几里得算法(Euclid) 背景: 欧几里德算法又称辗转相除法.用于计算两个正整数a.b的最大公约数. -- ...
- Java中接口和抽象类的比較
Java中接口和抽象类的比較-2013年5月写的读书笔记摘要 1. 概述 接口(Interface)和抽象类(abstract class)是 Java 语言中支持抽象类的两种机制,是Java程序设计 ...
- UI设计--->全心全意为人民服务的宗旨---->注重客户体验--->软件持久的生命力
UI即User Interface(用户界面)的简称. UI设计是指对软件的人机交互.操作逻辑.界面美观的总体设计. 好的UI设计不仅是让软件变得有个性有品味,还要让软件的操作变得舒适简单.自由.充分 ...
- Android之自己定义(上方标题随ViewPager手势慢慢滑动)
近期非常蛋疼,项目要模仿网易新闻的样式去做.上次把仿网易新闻client的下拉刷新写出来了.这次是ViewPager的滑动,同一时候ViewPager的上面标题下划线尾随者移动.本来通过ViewPag ...
- bzoj3673 & bzoj3674 & 洛谷P3402 可持久化并查集
题目:bzoj3673:https://www.lydsy.com/JudgeOnline/problem.php?id=3673 bzoj3674:https://www.lydsy.com/Jud ...
- django自带url模板标签的使用
django模板中url标签和view中的reverse(博客地址)功能相同,都是通过制定处理视图来返回一个url. 使用方法: {% url userEdit 12 %} 或者 {% url use ...
- java 格式化日期
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); simpleDat ...
- 1046: [HAOI2007]上升序列(dp)
1046: [HAOI2007]上升序列 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4999 Solved: 1738[Submit][Stat ...