spfa专题
SPFA专题
1通往奥格瑞玛的道路
在艾泽拉斯,有n个城市。编号为1,2,3,...,n。
城市之间有m条双向的公路,连接着两个城市,从某个城市到另一个城市,会遭到联盟的攻击,进而损失一定的血量。
每次经过一个城市,都会被收取一定的过路费(包括起点和终点)。路上并没有收费站。
假设1为暴风城,n为奥格瑞玛,而他的血量最多为b,出发时他的血量是满的。
歪嘴哦不希望花很多钱,他想知道,在可以到达奥格瑞玛的情况下,他所经过的所有城市中最多的一次收取的费用的最小值是多少。
输入输出格式
输入格式:
第一行3个正整数,n,m,b。分别表示有n个城市,m条公路,歪嘴哦的血量为b。
接下来有n行,每行1个正整数,fi。表示经过城市i,需要交费fi元。
再接下来有m行,每行3个正整数,ai,bi,ci(1<=ai,bi<=n)。表示城市ai和城市bi之间有一条公路,如果从城市ai到城市bi,或者从城市bi到城市ai,会损失ci的血量。
输出格式:
仅一个整数,表示歪嘴哦交费最多的一次的最小值。
如果他无法到达奥格瑞玛,输出AFK。
输入输出样例
输入样例#1: 复制
4 4 8
8
5
6
10
2 1 2
2 4 1
1 3 4
3 4 3
输出样例#1: 复制
10
说明
对于60%的数据,满足n≤200,m≤10000,b≤200
对于100%的数据,满足n≤10000,m≤50000,b≤1000000000
对于100%的数据,满足ci≤1000000000,fi≤1000000000,可能有两条边连接着相同的城市。
最大值最小?二分答案。但有血量怎么办?因为你想要走到奥格瑞玛,你不能死,那血扣的最少的时候你还死了说明不可能通过,也就是AFK。所以这可以刚开始用一个很大的答案试试,如果能通过,说明可行。然后二分答案,这里要注意一个大大大坑,你快排了cost,它所对应的节点也就改变了,就是说通过i节点的费用不是原来的了。所以你需要一个临时数组来代替cost快排,然后将这个数组作为二分答案的数组。他们两两不干扰。要注意数组后效性! |
var
x,y,z,n,m,b,mi,sum,l,r,mid,blood,ma,ans:int64;
a,w,cost,next,head,q,dis,c:array[..]of int64;
vis,bj:array[..]of boolean;
i,e:longint;
procedure sort(l,r:int64);
var
i,j,x,y:int64;
begin
i:=l;
j:=r;
x:=c[(l+r) div ];
repeat
while c[i]<x do
inc(i);
while x<c[j] do
dec(j);
if not(i>j) then
begin
y:=c[i];
c[i]:=c[j];
c[j]:=y;
inc(i);dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; procedure add(x,y,z:longint);
begin
inc(e);a[e]:=y;next[e]:=head[x];head[x]:=e;w[e]:=z;
end;
function check(mid:longint):boolean;
var h,t,u,v,i:longint;
begin
h:=;t:=;
fillchar(q,sizeof(q),);
fillchar(vis,sizeof(vis),false);
fillchar(bj,sizeof(bj),false);
q[]:=; vis[]:=true;
for i:= to n do dis[i]:=<<;
for i:= to n do if mid<cost[i] then bj[i]:=true;
dis[]:=;
while h<t do
begin
inc(h);
u:=q[h];
i:=head[u];
vis[u]:=false;
while i> do
begin
v:=a[i];
// if mid= then writeln(u,' ',v);
if (dis[u]+w[i]<dis[v])and(not bj[v]) then
begin
dis[v]:=dis[u]+w[i];
if (not vis[v])and(not bj[v]) then
begin
vis[v]:=true;
inc(t);
q[t]:=v;
end;
end;
i:=next[i];
end;
end;
if dis[n]>b then exit(false) else exit(true);
end;
begin
readln(n,m,b);
mi:=maxlongint;
for i:= to n do
begin
readln(cost[i]);
if ma<cost[i] then ma:=cost[i];
if mi>cost[i] then mi:=cost[i]; end;
c:=cost;
sort(,n);
for i:= to m do
begin
readln(x,y,z);
add(x,y,z);
add(y,x,z);
end;
l:=; r:=n;
if not check(maxlongint) then
begin writeln('AFK'); exit; end; while l<=r do
begin
mid:=(l+r)div ;
// blood:=b; if check(c[mid]) then
begin ans:=c[mid]; r:=mid-; end else l:=mid+;
end; writeln(ans);
end.
2 最优贸易noip2009
题解:
就因为我for 中m 打错成n就调了一个小时!?而且这已经不是第一次了!
------------------------------------------------------------------------------------
开始说正事。
本题很直观的就是想找到一个价格最低和一个价格最高点(满足由起点能到达, 且又可顺序到达终点),找最低价格的点可以这样来处理, 从源点开始找到所有点的最低价格(某个顶点的最低价格就是从源点到该所有可能路径上的价格最低的点), 最后枚举卖出的点,并且判断该点是否可以到达即可。 此外,由于数据规模较大,一般的邻接矩阵难以承受, 因此采用动态数据结构邻接表。但是本题有环,处理时还有几个细节问题: 1.由于是最后要判定所有的顶点是否可以到达终点, 因此不妨将所有的边反向,由终点出发判断终点可以到达那些顶点就可以了, 并做上标记。这样也就要求在读入边的时候必须反向再储存一次。 2.用SPFA求某个顶点的最低价格时,对SPFA进行了改进。 由SPFA的原理可以知道,该算法可以处理环的问题, 但是要求最短路径的长度是可以收敛的,也就是说不能在图中存在负权。 该题目满足此要求。SPFA是用来求最短路径的算法,在此对其改进, 来求路径上最小价格的点。
var
e,ie,x,y,z,u,h,t,n,m,i,j,k,ans,v:longint;
head,b,next,ihead,inext,a,ib,maxp,minp,q:array[..]of longint;
vis:array[..]of boolean;
function max(x,y:longint):longint;
begin
if x>y then exit(x) else exit(y);
end;
function min(x,y:longint):longint;
begin
if x>y then exit(y) else exit(x);
end;
procedure add(x,y:longint);
begin
inc(e);b[e]:=y;next[e]:=head[x];head[x]:=e;
end;
procedure iadd(x,y:longint);//反向建边
begin
inc(ie);ib[ie]:=y;inext[ie]:=ihead[x];ihead[x]:=ie;
end;
procedure spfa1;
var i,j,h,t,u,v:longint;
begin
for i:= to n do minp[i]:=maxlongint;
h:=;t:=; q[]:=;vis[]:=true;
minp[]:=a[];
while h<t do
begin
inc(h);
u:=q[h];
vis[u]:=false;
i:=head[u];
while i> do
begin
v:=b[i];
if minp[v]>minp[u] then
begin
minp[v]:=minp[u];
minp[v]:=min(minp[v],a[v]);
if not vis[v] then
begin
vis[v]:=true;
inc(t);
q[t]:=v;
end;
end;
i:=next[i];
end;
end; end;
procedure spfa2;
var i,j,h,t,u,v:longint;
begin
fillchar(q,sizeof(q),);
fillchar(vis,sizeof(vis),false);
h:=;t:=;
q[]:=n; vis[n]:=true;
maxp[n]:=a[n];
while h<t do
begin
inc(h);
u:=q[h];
i:=ihead[u];
vis[u]:=false;//打在前面有负环也能运行
while i> do
begin
v:=ib[i];
if maxp[v]<maxp[u] then // you wrong here
begin
maxp[v]:=maxp[u];
maxp[v]:=max(maxp[v],a[v]);
if not vis[v] then
begin
vis[v]:=true;
inc(t);
q[t]:=v;
end;
end;
i:=inext[i]; end;
end; end;
begin
readln(n,m);
for i:= to n do
read(a[i]);
for i:= to m do//m 不要再打成n了!
begin
readln(x,y,z);
add(x,y);
iadd(y,x);
if z= then
begin
add(y,x);
iadd(x,y);
end;
end;
spfa1;
spfa2;
for i:= to n do
if maxp[i]-minp[i]>ans then ans:=maxp[i]-minp[i];
writeln(ans);
end.
spfa专题的更多相关文章
- [bzoj2118]墨墨的等式【dijk+堆】
10/30的update:如果是冲着dijk的板子来的,建议看多校联考contest中第二场day2的T2,那边的写法比较优秀... --------------------------------- ...
- 算法专题 | 10行代码实现的最短路算法——Bellman-ford与SPFA
今天是算法数据结构专题的第33篇文章,我们一起来聊聊最短路问题. 最短路问题也属于图论算法之一,解决的是在一张有向图当中点与点之间的最短距离问题.最短路算法有很多,比较常用的有bellman-ford ...
- 【算法系列学习】SPFA邻接表最短路 [kuangbin带你飞]专题四 最短路练习 F - Wormholes
https://vjudge.net/contest/66569#problem/F 题意:判断图中是否存在负权回路 首先,介绍图的邻接表存储方式 数据结构:图的存储结构之邻接表 邻接表建图,类似于头 ...
- 并不对劲的图论专题(三):SPFA算法的优化
1.bzoj1489-> 这是个新套路. 我们希望找到最小的x,那么可以二分x,然后判断是否存在圈的边权的平均值小于等于x. 设圈的边权依次为w1,w2,w3,…,wk,平均值为p, 则有p= ...
- CSU1333最短路问题SPFA
fastvj.rainng.com/contest/236779#problem/I Description: n个点m条路每条路 l,r,t:表示这条路开l秒,关r秒,通过要t秒,问你车辆从s到t最 ...
- LightOJ 1074 - Extended Traffic (SPFA)
http://lightoj.com/volume_showproblem.php?problem=1074 1074 - Extended Traffic PDF (English) Stati ...
- [专题总结]初探插头dp
彻彻底底写到自闭的一个专题. 就是大型分类讨论,压行+宏定义很有优势. 常用滚动数组+哈希表+位运算.当然还有轮廓线. Formula 1: 经过所有格子的哈密顿回路数. 每个非障碍点必须有且仅有2个 ...
- 学习笔记--APIO 2018 二分专题 By wuvin
前言: 在APIO 2018 Day2下午听wuvin讲二分,听了一上午的神仙,现在终于有可以听懂了. 专题: 平均边权最大 题目链接:https://www.questoj.cn/problem/3 ...
- NOIp 图论算法专题总结 (1):最短路、最小生成树、最近公共祖先
系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 最短路 Floyd 基本思路:枚举所有点与点的中点,如果从中点走最短,更新两点间 ...
随机推荐
- 如何使用Putty登录安装在VirtualBox里的ubuntu
我是在Windows操作系统里用VirtualBox安装了ubuntu操作系统. 在VirtualBox里操作ubuntu的终端不是很方便,比如我想在Windows里复制一些命令到ubuntu的终端执 ...
- 构建高性能插件式Web框架
基于MVC插件模式构建支持数据库集群.数据实时同步.数据发布与订阅的Web框架系统.如下图: 1.基于插件式开发 采用插件模式开发的优点是使得系统框架和业务模式有效地进行分离,系统更新也比较简单,只需 ...
- 【转载】SSH login without password 免密登陆
Your aim You want to use Linux and OpenSSH to automate your tasks. Therefore you need an automatic l ...
- BZOJ3531:[SDOI2014]旅行(树链剖分)
Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰 ...
- 深搜(DFS),回溯,Fire Net
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=2 解题报告: 这里的深搜有一点不同,就是,在深搜每一个点时,都要深搜每 ...
- 【bzoj2563】 阿狸和桃子的游戏
题目 非常妙的题目,一看到就以为是一道博弈,之后就不会做了 正解非常巧妙,由于我们只需要求出最后两个人得分的差值,所以对于每一条边我们将其的权值拆成两边,分给其连接的两个点 如果这两个点被同一个人选择 ...
- javascript之正则表达式基础知识小结
javascript之正则表达式基础知识小结,对于学习正则表达式的朋友是个不错的基础入门资料. 元字符 ^ $ . * + ? = ! : | \ / ( ) [ ] { } 在使用这些符号时需要 ...
- Caffe计算net、layer向前向后传播时间
在caffe中计算某个model的整个net以及各个layer的向前向后传播时间,可以使用下面的命令格式: ./build/tools/caffe time --model=examples/mnis ...
- 【luogu P3901 数列找不同】 题解
对于区间查询的问题,提供一种思路: 莫队. 莫队是处理区间问题的乱搞神器,尤其是对于离线查询问题,当然也可以做在线查询,比如带修莫队. 对于有的题,莫队是乱搞骗分,而在某些地方,莫队是正解. 这道题来 ...
- 【luogu P1455 搭配购买】 题解
题目链接:https://www.luogu.org/problemnew/show/P1455 一句话题目做法:并查集合并+01背包 启示:要每次再find一遍.路径压缩会快.因为合并的时候如果是1 ...