【算法】分层图最短路

【题解】

考虑k层一模一样的图,然后每个夹层都在每条边的位置新加从上一层跨越到下一层的边权为0的边,这样至多选择k条边置为0。

然后考虑方便的写法。

SPFA

第一次SPFA计算常规最短路(顶层)。

之后k次SPFA,松弛操作加上可以从上一层节点直接获取最短路(即相当于省一条边)

这样可以保证一次SPFA最多只有一条边省略,因为你要么从上一层前一个点下来,其实是获取上一层前一个点的最短路。

要么从前面一个点过来,其实是获取本层的最短路,本层最短路最多从上面下来一次。

因为只与上一层有关,开滚动数组。

SPFA记得SLF优化,不然较慢!

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxm=,maxn=;
struct edge{int v,w,from;}e[maxm*];
int first[maxn],X,n,m,k,q[],tot=;
long long d[][maxn];
bool vis[maxn];
void insert(int u,int v,int w)
{tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}
void spfa()
{
memset(vis,,n+);
memset(d[X],0x3f,*(n+));
int head=,tail=;q[]=;vis[]=;d[X][]=;
while(head!=tail)
{
int x=q[head++];if(head>)head=;
for(int i=first[x];i;i=e[i].from)
if(d[X][e[i].v]>d[X][x]+e[i].w)
{
int y=e[i].v;
d[X][y]=d[X][x]+e[i].w;
if(!vis[e[i].v])
{
if(d[X][y]<d[X][q[head]]){head--;if(head<)head=;q[head]=y;}
else{q[tail++]=y;if(tail>)tail=;}
vis[e[i].v]=;
}
}
vis[x]=;
}
// for(int i=1;i<=n;i++)printf("%d ",d[X][i]);printf("\n");
}
void spfas()
{
// for(int i=1;i<=n;i++)d[X][i]=d[1-X][i];
memset(d[X],0x3f,*(n+));
int head=,tail=;q[]=;vis[]=;d[X][]=;
while(head!=tail)
{
int x=q[head++];if(head>)head=;//printf("q %d",x);
for(int i=first[x];i;i=e[i].from)
if(d[X][e[i].v]>min(d[X][x]+e[i].w,d[-X][x]))
{
int y=e[i].v;
d[X][y]=min(d[X][x]+e[i].w,d[-X][x]);
if(!vis[e[i].v])
{
if(d[X][y]<d[X][q[head]]){head--;if(head<)head=;q[head]=y;}
else{q[tail++]=y;if(tail>)tail=;}
vis[e[i].v]=;
}
}
vis[x]=;
}
// for(int i=1;i<=n;i++)printf("%d ",d[X][i]);printf("\n");
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
insert(u,v,w);
insert(v,u,w);
}
X=;
spfa();
for(int i=;i<=k;i++)
{
X=-X;
spfas();
}
printf("%lld",d[X][n]);
return ;
}

Dijkstra

效率相似,但是写法简单很多,只要记录多一维层次,每次更新的时候附带上到下一层的更新,然后根据dij每次选择最短的更新的特点,第一次到达n就是答案了。

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=;
struct edge{int v,w,from;}e[maxn];
struct cyc{
int x,k,d;
bool operator < (const cyc &a)const{
return d>a.d;
}
};
priority_queue<cyc>q;
int n,m,first[maxn],tot,d[maxn][],kind; void insert(int u,int v,int w){
tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;
tot++;e[tot].v=u;e[tot].w=w;e[tot].from=first[v];first[v]=tot;
}
int dijkstra(){
q.push((cyc){,,});
memset(d,0x3f,sizeof(d));
d[][]=;
while(!q.empty()){
cyc x=q.top();q.pop();
if(x.d!=d[x.x][x.k])continue;
if(x.x==n)return x.d;
for(int i=first[x.x];i;i=e[i].from){
if(d[e[i].v][x.k]>d[x.x][x.k]+e[i].w){d[e[i].v][x.k]=d[x.x][x.k]+e[i].w;q.push((cyc){e[i].v,x.k,d[e[i].v][x.k]});}
if(x.k<kind&&d[e[i].v][x.k+]>d[x.x][x.k]){d[e[i].v][x.k+]=d[x.x][x.k];q.push((cyc){e[i].v,x.k+,d[e[i].v][x.k+]});}
}
}
return ;
}
int main(){
scanf("%d%d%d",&n,&m,&kind);
int u,v,w;
for(int i=;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
insert(u,v,w);
}
printf("%d",dijkstra());
return ;
}

【BZOJ】1579: [Usaco2009 Feb]Revamping Trails 道路升级的更多相关文章

  1. Bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 dijkstra,堆,分层图

    1579: [Usaco2009 Feb]Revamping Trails 道路升级 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1573  Solv ...

  2. BZOJ 1579: [Usaco2009 Feb]Revamping Trails 道路升级( 最短路 )

    最短路...多加一维表示更新了多少条路 -------------------------------------------------------------------------------- ...

  3. bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 -- 分层图最短路

    1579: [Usaco2009 Feb]Revamping Trails 道路升级 Time Limit: 10 Sec  Memory Limit: 64 MB Description 每天,农夫 ...

  4. bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 优先队列+dij

    1579: [Usaco2009 Feb]Revamping Trails 道路升级 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1768  Solv ...

  5. bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级——分层图+dijkstra

    Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i ...

  6. BZOJ 1579 [Usaco2009 Feb]Revamping Trails 道路升级:dijkstra 分层图【将k条边改为0】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1579 题意: 给你一个无向图,n个点,m条边,每条边有边权w[i]. 你可以将其中的k(k ...

  7. BZOJ 1579: [Usaco2009 Feb]Revamping Trails 道路升级 分层图最短路 + Dijkstra

    Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i ...

  8. bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级【分层图+spfa】

    至死不用dijskstra系列2333,洛谷上T了一个点,开了O2才过 基本想法是建立分层图,就是建k+1层原图,然后相邻两层之间把原图的边在上一层的起点与下一层的终点连起来,边权为0,表示免了这条边 ...

  9. BZOJ 1579 [Usaco2009 Feb]Revamping Trails 道路升级

    堆优化的dijkstra. 把一个点拆成k个. 日常空间要开炸一次.. //Twenty #include<cstdio> #include<cstring> #include ...

  10. 【BZOJ 1579】 1579: [Usaco2009 Feb]Revamping Trails 道路升级 (最短路)

    1579: [Usaco2009 Feb]Revamping Trails 道路升级 Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M< ...

随机推荐

  1. 近期准备发布我的asp.net框架

    此框架为超轻量级架构,适合做中小型的b/s项目

  2. Qt C++ 并发,并行,多线程编程系列1 什么是并发

    什么是并发,并发往简单来说就是两个或多个独立的任务同时发生,在我们的生活中也是随处可见.如果把每个人都当作一个独立的任务,那每个人可以相互独立的生活,这就是并发. 在计算机的系统里面,并发一般有两种, ...

  3. 9.0 toast定位+WebDriverWait显示等待

    Toast  判断-----基本操作问题 首先基本操作,进入安卓市场的账号密码页面--- from appium import webdriver from selenium.webdriver.su ...

  4. git部署详解

    1.1 关于版本控制 1.1.1 本地版本控制 本地版本控制系统 许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别.这么做唯一的 好处就是简单,但是特别容易犯错.有 ...

  5. DPDK vhost库

    原创翻译,转载请注明出处. vhost库实现了一个用户空间的virtio net server,允许用户直接处理virtio ring队列.换句话说,它让用户可以从VM virtio网络设备读取或写入 ...

  6. Mybatis学习系列(一)入门简介

    MyBatis简介 Mybatis是Apache的一个Java开源项目,是一个支持动态Sql语句的持久层框架.Mybatis可以将Sql语句配置在XML文件中,避免将Sql语句硬编码在Java类中.与 ...

  7. [Elasticsearch] 多字段搜索 (二) - 最佳字段查询及其调优

    最佳字段(Best Fields) 假设我们有一个让用户搜索博客文章的网站,就像这两份文档一样: PUT /my_index/my_type/1 { "title": " ...

  8. 使用window.getSelection()获取div中选中文字内容及位置

    div添加一个弹出事件: $(document).ready(function () { $("#marked-area").mouseup(function (e) { $sco ...

  9. Citrix Netscaler负载均衡算法

    Citrix Netscaler负载均衡算法 http://blog.51cto.com/caojin/1926308 众所周知,作为新一代应用交付产品的Citrix Netscaler具有业内领先的 ...

  10. Netscaler的超高端口复用助力应对公网地址紧张

    Netscaler的超高端口复用助力应对公网地址紧张 http://blog.51cto.com/caojin/1898351 经常会有人问一个IP只有65535(姑且不考虑预留端口),从Big-ip ...