P4568 飞行路线【分层图最短路】
题目链接:https://www.luogu.org/problem/P4568
题目大意:给定n个点,m条无向边,k次机会经过边时代价为 0 。给出起点和终点,求其最短路径。
解题思路:
两种方法,一是用拆点分层,直接跑最短路。二是dis[][]开二维数组,表示已经用了 j 次免费机会时在 i 点的最短路径。
第一种方法数组需要多开大很多倍(因为拆点),当层数以及点比较多的时候,边也就非常多,代码跑起来很慢,在这里若不用优先队列dijsktra优化会超时。
第二种方法似乎更加好,不需要将一维数组开大很多倍,只需要用二维数组记录状态,然后更新即可。跑的边也会比较的少。代码更快。
对于第一种方法。图如下:

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
const int MAXN = 1e6 + ;//建了多层 点成倍增加
const int MAXM = 5e6 + ;
const int inf = 0x3f3f3f3f;
using namespace std; int n, m, k, st, ed;
int head[MAXN], cnt;
int vis[MAXN];
ll dis[MAXN]; //距离开ll 稳 struct Edge
{
int to, next;
ll w;
}edge[MAXM]; struct Node
{
int pot;
ll dis;
bool operator < (const Node &a)const
{
return dis > a.dis;
}
}node; void add(int a, int b, ll c)
{
cnt ++;
edge[cnt].to = b;
edge[cnt].w = c;
edge[cnt].next = head[a];
head[a] = cnt;
} void dij()
{
mem(dis, inf), mem(vis, );
priority_queue<Node> Q; //记得是优先队列
while(!Q.empty()) Q.pop();
dis[st] = ;
node.pot = st, node.dis = ;
Q.push(node);
while(!Q.empty())
{
Node a = Q.top();//top()
Q.pop();
if(vis[a.pot])
continue;
vis[a.pot] = ;
for(int i = head[a.pot]; i != -; i = edge[i].next)
{
int to = edge[i].to;
if(vis[to]) //若该点以及确定了最短距离 则不需要再去比较了
continue;
if(dis[to] > dis[a.pot] + edge[i].w)
{
dis[to] = dis[a.pot] + edge[i].w;
node.pot = to, node.dis = dis[to];
Q.push(node);
}
}
}
} int main()
{
cnt = , mem(head, -);
scanf("%d%d%d", &n, &m, &k);
scanf("%d%d", &st, &ed);
for(int i = ; i <= m; i ++)
{
int a, b;
ll c;
scanf("%d%d%lld", &a, &b, &c);
add(a, b, c);
add(b, a, c);
for(int j = ; j <= k; j ++)
{
add(a + (j - ) * n, b + j * n, ); //上一层往下一层建边权为 0 的边
add(b + (j - ) * n, a + j * n, );
add(a + j * n, b + j * n, c); //每一层本身的边也要建
add(b + j * n, a + j * n, c);
}
}
dij();
ll ans = inf;
for(int i = ; i <= k; i ++) //选择到终点距离最短的那一层答案
ans = min(ans, dis[ed + i * n]);
printf("%lld\n", ans);
return ;
}
建图时分层
#include<stdio.h>
#include<string.h>
#include<queue>
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
const int MAXN = 1e4 + ;
const int MAXM = 5e4 + ;
const int inf = 0x3f3f3f3f;
using namespace std; int n, m, k, st, ed;
int head[MAXN], cnt, vis[MAXN][];
ll dis[MAXN][]; struct Edge
{
int to, next;
ll w;
}edge[ * MAXM]; struct Node
{
int pot, num; //点 以及 用了的机会次数
ll dis;
bool operator < (const Node &a)const
{
return dis > a.dis;
}
}node; void add(int a, int b, ll c)
{
cnt ++;
edge[cnt].w = c;
edge[cnt].to = b;
edge[cnt].next = head[a];
head[a] = cnt;
} void dij()
{
mem(dis, inf), mem(vis, );
node.pot = st, node.dis = , node.num = ;
dis[st][] = ;
priority_queue<Node> Q;
Q.push(node);
while(!Q.empty())
{
Node a = Q.top();
Q.pop();
if(vis[a.pot][a.num])
continue;
vis[a.pot][a.num] = ;
for(int i = head[a.pot]; i != -; i = edge[i].next)
{
int to = edge[i].to;
if(dis[to][a.num] > dis[a.pot][a.num] + edge[i].w) //不使用免费机会
{
dis[to][a.num] = dis[a.pot][a.num] + edge[i].w;
node.pot = to, node.dis = dis[to][a.num], node.num = a.num;
Q.push(node);
}
if(a.num == k) //如果已经把免费机会使用完了
continue;
if(dis[to][a.num + ] > dis[a.pot][a.num])
{
dis[to][a.num + ] = dis[a.pot][a.num];
node.pot = to, node.dis = dis[to][a.num + ], node.num = a.num + ;
Q.push(node);
}
}
}
} int main()
{
mem(head, -), cnt = ;
scanf("%d%d%d", &n, &m, &k);
scanf("%d%d", &st, &ed);
for(int i = ; i <= m; i ++)
{
int a, b;
ll c;
scanf("%d%d%lld", &a, &b, &c);
add(a, b, c);
add(b, a, c);
}
dij();
ll ans = inf;
for(int i = ; i <= k; i ++)
ans = min(ans, dis[ed][i]);
printf("%lld\n", ans);
return ;
}
二维数组
P4568 飞行路线【分层图最短路】的更多相关文章
- P4568 飞行路线 分层图最短路
P4568 飞行路线 分层图最短路 分层图最短路 问题模型 求最短路时,可有\(k\)次更改边权(减为0) 思路 在普通求\(Dijkstra\)基础上,\(dis[x][j]\)多开一维\(j\)以 ...
- bzoj2763 [JLOI]飞行路线 分层图最短路
问题描述 Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的 ...
- P4568 [JLOI2011]飞行路线 分层图最短路
思路:裸的分层图最短路 提交:1次 题解: 如思路 代码: #include<cstdio> #include<iostream> #include<cstring> ...
- BZOJ2763: [JLOI2011]飞行路线(分层图 最短路)
题意 题目链接 Sol 分层图+最短路 建\(k+1\)层图,对于边\((u, v, w)\),首先在本层内连边权为\(w\)的无向边,再各向下一层对应的节点连边权为\(0\)的有向边 如果是取最大最 ...
- [JLOI2011]飞行路线 分层图最短路
题目描述: Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在nn个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一 ...
- 【bzoj2763】[JLOI2011]飞行路线 分层图最短路
题目描述 Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的 ...
- bzoj 2763: [JLOI2011]飞行路线 -- 分层图最短路
2763: [JLOI2011]飞行路线 Time Limit: 10 Sec Memory Limit: 128 MB Description Alice和Bob现在要乘飞机旅行,他们选择了一家相 ...
- BZOJ2763[JLOI2011]飞行路线 [分层图最短路]
2763: [JLOI2011]飞行路线 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2523 Solved: 946[Submit][Statu ...
- [JLOI2011]飞行路线 (分层图,最短路)
题目链接 Solution 建立 \(k+1\) 层图跑 \(Dijkstra\) 就好了. Code #include<bits/stdc++.h> #define ll long lo ...
- [bzoj2763][JLOI2011]飞行路线——分层图最短路
水题.不多说什么. #include <bits/stdc++.h> using namespace std; const int maxn = 10010; const int maxk ...
随机推荐
- Jquery使用心得
1.<form>提交时,会提交里面有name属性的元素,而不是id属性 $("#form").serialize(); 得到里面每个元素的拼接值 id=1& ...
- plupload上传整个文件夹
大容量文件上传早已不是什么新鲜问题,在.net 2.0时代,HTML5也还没有问世,要实现这样的功能,要么是改web.config,要么是用flash,要么是用一些第三方控件,然而这些解决问题的方法要 ...
- 如何安全的从LVM中移除磁盘
学习如何安全的从LVM中移除磁盘,当磁盘卷中有磁盘出现问题或是想把磁盘卷中的磁盘重新使用时就显得十分有用.本教程将重点关注以下问题: 如何安全的从LVM中移除磁盘 如何联机从VG中移除磁盘 如 ...
- 模拟I2C协议学习点滴之程序相关定义
由于主机和从机都会给数据线SDA发信号,比如主机先给SDA发送数据后,从机收到数据后发送应答信号将SDA拉低,故SDA类型设定为inout.而DATA设定为inout类型,是起到校验通信的作用(后续的 ...
- jQuery多选和单选下拉框插件select.js
一.插件描述 可通过参数设置多选或者单选,多选返回数组结果,单选返回字符串,如图: 下载地址:https://pan.baidu.com/s/1JjVoK89_ueVVpfSlMDJwUQ 提取码 ...
- 实现返回顶部-wepy小程序-前端梳理
<script type="text/javascript" src="http://hovertree.com/ziyuan/jquery/jquery-1.11 ...
- PHP全栈学习笔记20
thinkphp概述,thinkphp项目构建流程,thinkphp项目结构,thinkphp配置,thinkphp控制器,thinkphp模型,thinkphp视图,thinkphp的内置模板引擎. ...
- 卸载ros
#卸载 ros sudo apt-get autoremove ros-*
- Entity Framework 一个表多个外键关联另外一张表的相同主键
一. 报错 异常:System.Data.Entity.Infrastructure.DbUpdateException: 更新条目时出错.有关详细信息,请参阅内部异常. ---> System ...
- 如何计算一个C/C++程序运行时间
前两天要计算一个用C++实现的算法运行时间,就用了clock()这个函数.程序大体上如下: clock_t start,end; start = clock(); /*my code*/ end = ...