HDU6582 Path【优先队列优化最短路 + dinic最大流 == 最小割】
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6582
来源:2019 Multi-University Training Contest 1
题目大意:
给定一张有向图,可以阻碍若干条有向边,花费为边的权值,求使其最短路变得更长所需的最小花费。
解题思路:
1.因为最短路可能是多条,所以找出最短路网络,然后在最短路网络中跑最小割,即最大流。就切断了原先的最短路且保证了是最小花费(最小割)。
2.值得注意的地方:边的长度限制为1e9,所以最短路数组以及一些其他的求和的值要开long long型,防止爆。
3.求最短路核心边需满足 dis[u] + edge[i].w == dis[v]。那么edge[i].w就是一条最短路的核心边。同时要确保合法性,满足dis[u] != inf && dis[v] != inf
代码如下:
#include<stdio.h>
#include<string.h>
#include<queue>
#define LL long long
#define mem(a, b) memset(a, b, sizeof(a))
const int MAXN = 1e4 + ;
const LL inf = 0x3f3f3f3f;
using namespace std; int n, m;//n个点 m条有向边
int vis[MAXN];//源点到该点的最短距离是否被确定
LL dis[MAXN]; struct Edge
{
int to, next;
LL w;
}e[MAXN];
int head[MAXN], cnt; void add(int a, int b, int c)
{
e[++ cnt].to = b;
e[cnt].w = c;
e[cnt].next = head[a];
head[a] = cnt;
} struct Node
{
int pot;
LL dis; //点 以及 源点到该点的最短距离
bool operator < (const Node &a)const//重载 按照dis从小到大排序
{
return dis > a.dis;
}
}no; priority_queue<Node> Q;
void dij() //优先队列优化的最短路
{
mem(vis, ), mem(dis, inf);
no.dis = , no.pot = ;
dis[] = ;
Q.push(no);
while(!Q.empty())
{
Node a = Q.top();//优先队列无front操作
Q.pop();
if(vis[a.pot])
continue;
vis[a.pot] = ;
for(int i = head[a.pot]; i != -; i = e[i].next)//松弛操作
{
int to = e[i].to;
if(!vis[to] && dis[a.pot] + e[i].w < dis[to])
{
dis[to] = dis[a.pot] + e[i].w;
no.pot = to, no.dis = dis[to];
Q.push(no);
}
}
}
// printf("%d\n", dis[n]);
} struct edge_
{
int to, next, flow;
}e_[ * MAXN];//要加反向边 开2倍
int head_[MAXN]; void add_(int a, int b, int c)
{
e_[++ cnt].to = b;
e_[cnt].flow = c;
e_[cnt].next = head_[a];
head_[a] = cnt;
} int dep[MAXN];
int bfs(int st, int ed)
{
if(st == ed)
return ;
mem(dep, -);
queue<int >Q_;
dep[st] = ;
Q_.push(st);
while(!Q_.empty())
{
int now = Q_.front();
Q_.pop();
for(int i = head_[now]; i != -; i = e_[i].next)
{
int to = e_[i].to;
if(e_[i].flow > && dep[to] == -)
{
dep[to] = dep[now] + ;
Q_.push(to);
}
}
}
return dep[ed] != -;
} int dfs(int now, int ed, int inc)
{
if(now == ed)
return inc;
for(int i = head_[now]; i != -; i = e_[i].next)
{
int to = e_[i].to;
if(e_[i].flow > && dep[to] == dep[now] + )
{
int min_flow = dfs(to, ed, min(inc, e_[i].flow));
if(min_flow > )
{
e_[i].flow -= min_flow;
e_[i ^ ].flow += min_flow;
return min_flow;
}
}
}
return -;
} LL dinic(int st, int ed)
{
LL ans = ;
while(bfs(st, ed))
{
while()
{
int inc = dfs(st, ed, inf);
if(inc == -)
break;
ans += inc;
}
}
return ans;
} int main()
{
int T;
scanf("%d", &T);
while(T --)
{
scanf("%d%d", &n, &m);
cnt = , mem(head, -); //最短路的边从1开始存 head初始化为-1
for(int i = ; i <= m; i ++)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c); //有向边 加一条即可
}
dij(); //跑最短路
if(dis[n] == inf) //特判
{
printf("0\n");
continue;
}
cnt = -, mem(head_, -);//从0开始存 才能进行 ^ 运算
for(int i = ; i <= n; i ++)
{
for(int j = head[i]; j != -; j = e[j].next)
{
int to = e[j].to;
if(dis[i] + e[j].w == dis[to] && dis[to] != inf && dis[i] != inf) //得到最短路核心边(因为可能是多条)
{
add_(i, to, e[j].w);
add_(to, i, ); //反向边容量为 0
}
}
}
printf("%lld\n", dinic(, n));
}
return ;
}
优先队列优化dij+最大流dinic
HDU6582 Path【优先队列优化最短路 + dinic最大流 == 最小割】的更多相关文章
- 2020牛客暑期多校训练营 第二场 I Interval 最大流 最小割 平面图对偶图转最短路
LINK:Interval 赛时连题目都没看. 观察n的范围不大不小 而且建图明显 考虑跑最大流最小割. 图有点稠密dinic不太行. 一个常见的trick就是对偶图转最短路. 建图有点复杂 不过建完 ...
- hdu 2435 dinic算法模板+最小割性质
#include<stdio.h> #include<queue> #include<string.h> using namespace std; #define ...
- 晴天小猪历险记之Hill(Dijkstra优先队列优化)
描述 这一天,他来到了一座深山的山脚下,因为只有这座深山中的一位隐者才知道这种药草的所在.但是上山的路错综复杂,由于小小猪的病情,晴天小猪想找一条需时最少的路到达山顶,但现在它一头雾水,所以向你求助. ...
- 2019HDU多校Path——最短路最小割
题目 给出一个 $n$ 个顶点 $m$ 条边的图,要求阻塞一些边,使得从 $1$ 到 $n$ 的最短路变长,求阻塞的边长度和的最小值,不必保证阻塞后可达. 分析 很显然,要阻塞的边肯定在最短路图上,先 ...
- Luogu2046 NOI2010 海拔 平面图、最小割、最短路
传送门 首先一个不知道怎么证的结论:任意点的\(H\)只会是\(0\)或\(1\) 那么可以发现原题的本质就是一个最小割,左上角为\(S\),右下角为\(T\),被割开的两个部分就是\(H=0\)与\ ...
- cf786E ALT (最小割+倍增优化建图)
如果把“我全都要”看作是我全不要的话,就可以用最小割解决啦 源点S,汇点T 我们试图让每个市民作为一个等待被割断的路径 把狗狗给市民:建边(S,i,1),其中i是市民 把狗狗给守卫:建边(j,T,1) ...
- 最短路算法模板合集(Dijkstar,Dijkstar(优先队列优化), 多源最短路Floyd)
再开始前我们先普及一下简单的图论知识 图的保存: 1.邻接矩阵. G[maxn][maxn]; 2.邻接表 邻接表我们有两种方式 (1)vector< Node > G[maxn]; 这个 ...
- POJ 1511 Invitation Cards(单源最短路,优先队列优化的Dijkstra)
Invitation Cards Time Limit: 8000MS Memory Limit: 262144K Total Submissions: 16178 Accepted: 526 ...
- hdu 1874(最短路 Dilkstra +优先队列优化+spfa)
畅通工程续 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
随机推荐
- python 使用流式游标 读取mysql怎么不会内存溢出
使用过java读取mysql大数据量的人应该都知道,如果查询时不开游标不设置一次性区大小的话,会一次性的把所有记录都拉取过来再进行后续操作,数据量一大就很容易出现OOM 如果用python去读取mys ...
- Shell 06 awk
一.基本操作方法 ######################################### grep 按行进行查找 vim 编辑文档,交互式 ####################### ...
- 创建第一个springboot项目,maven project
- css偷懒神奇
偷懒神奇链接:https://qishaoxuan.github.io/css_tricks/glass/
- Python学习日记(四)——Python基本数据类型梳理(int、str、list、tuple、dict)
数字(int) 1.创建方式 n1 = 123 n2 = int(123) 2.内存分配 #共同用一个内存地址的情况 n1 = 123 n2 = n1 #用两个内存地址的情况 n1 = 123 n2 ...
- 【Golang】嗅探抓包,解决线上偶现问题来不及抓包的情况
背景 测试群里经常看到客户端的同学反馈发现了偶现Bug,但是来不及抓包,最后不了了之,最近出现得比较频繁,所以写个小脚本解决这个问题. 实现思路 实现的思路比较简单: 抓包 存日志 做日志管理 具体实 ...
- 了解Spring Boot的自动配置
摘自:https://www.jianshu.com/p/ddb6e32e3faf Spring Boot的自动配置给开发者带来了很大的便利,当开发人员在pom文件中添加starter依赖后,mave ...
- 攻防世界Hello,CTF writeup
解题过程 首先在ida中进行反汇编,查看main函数的代码: 代码的的36行处进行了一个字符串比较,如果v10的值等于v13的值会反馈一个success的输出.v13的值在第15行给出,因此需要知道v ...
- zookeeper源码 — 五、处理写请求过程
目录 处理写请求总体过程 客户端发起写请求 follower和leader交互过程 follower发送请求给客户端 处理写请求总体过程 zk为了保证分布式数据一致性,使用ZAB协议,在客户端发起一次 ...
- SCRIPT438: 对象不支持“trim”属性或方法
关于ie9以下不支持trim()方法 可以在自己封装的框架中加入如下.或直接调用也行. if(!String.prototype.trim) { String.prototype.trim = fun ...