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自学] day-22 (1) (Session、CSRF、中间件)
一.响应函数补充 三种返回响应的方式: return HttpResponse() return render() return redirect() HttpResponse: 除了能够返回字符串, ...
- linux重启之后No CUDA-supporting devices found!
实验室做并行计算的服务重启后,采用cuda接口的应用程序vasp_gpu,运行时提示: CUDA Error in cuda_main.cu, line 144: unknown error No C ...
- sql 存储过程记录
-- exec sp_helptext add_book1 CREATE proc add_book1 --创建存储过程 @DocCode VARCHAR() --创建参数 as BEGIN INSE ...
- bufferedinputstream FileInputStream inputstream的比较
BufferedInputStream类相比InputStream类,提高了输入效率,增加了输入缓冲区的功能 不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多 ...
- windows游戏编程X86实模式和保护模式
本系列文章由jadeshu编写,转载请注明出处.http://blog.csdn.net/jadeshu/article/details/22309359 作者:jadeshu 邮箱: jades ...
- P2051 [AHOI2009]中国象棋——DP(我是谁,我在哪,为什么)
象棋,给你棋盘大小,然后放炮(炮的数量不限),不能让炮打到其他的炮,问方案数: 数据n,m<=200; 状态压缩似乎能做,但是我不会: 因为只要状态数,所以不必纠结每种状态的具体情况: 可以想出 ...
- shell 字符串分割cut
cut 选项与参数 -d:后面接分隔字符.与-f一起使用. -f:依据-d的分隔字符将一段信息分隔数段,用-f取出第几段的意思. -c:以字符的单位取出固定字符区间 [zhang@localhost ...
- window.innerHeight与document.documentElement.clientHeight与document.body.clientHeight区别
window.innerHeight属于BOM(浏览器对象模型),获取的高度包含横向滚动条 document.documentElement.clientHeight属于文档对象模型,不包含横向滚动条 ...
- Postgresql - MATERIALIZED VIEW
MATERIALIZED VIEWPG 9.3 版本之后开始支持物化视图.View 视图:虚拟,不存在实际的数据,在查询视图的时候其实是对视图内的表进行查询操作. 物化视图:实际存在,将数据存成一张表 ...
- 使用vagrant一键部署本地php开发环境(一)
一:我们为什么需要用这玩意 我们在开发中经常会面临的问题:环境不一致,有人用Mac有人用Windos还有几个用linux的,而我们的服务器都是linux. 在我本地是可以的啊,我测了都,没有问题 ...