题目链接: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 飞行路线【分层图最短路】的更多相关文章

  1. P4568 飞行路线 分层图最短路

    P4568 飞行路线 分层图最短路 分层图最短路 问题模型 求最短路时,可有\(k\)次更改边权(减为0) 思路 在普通求\(Dijkstra\)基础上,\(dis[x][j]\)多开一维\(j\)以 ...

  2. bzoj2763 [JLOI]飞行路线 分层图最短路

    问题描述 Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的 ...

  3. P4568 [JLOI2011]飞行路线 分层图最短路

    思路:裸的分层图最短路 提交:1次 题解: 如思路 代码: #include<cstdio> #include<iostream> #include<cstring> ...

  4. BZOJ2763: [JLOI2011]飞行路线(分层图 最短路)

    题意 题目链接 Sol 分层图+最短路 建\(k+1\)层图,对于边\((u, v, w)\),首先在本层内连边权为\(w\)的无向边,再各向下一层对应的节点连边权为\(0\)的有向边 如果是取最大最 ...

  5. [JLOI2011]飞行路线 分层图最短路

    题目描述: Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在nn个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一 ...

  6. 【bzoj2763】[JLOI2011]飞行路线 分层图最短路

    题目描述 Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的 ...

  7. bzoj 2763: [JLOI2011]飞行路线 -- 分层图最短路

    2763: [JLOI2011]飞行路线 Time Limit: 10 Sec  Memory Limit: 128 MB Description Alice和Bob现在要乘飞机旅行,他们选择了一家相 ...

  8. BZOJ2763[JLOI2011]飞行路线 [分层图最短路]

    2763: [JLOI2011]飞行路线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2523  Solved: 946[Submit][Statu ...

  9. [JLOI2011]飞行路线 (分层图,最短路)

    题目链接 Solution 建立 \(k+1\) 层图跑 \(Dijkstra\) 就好了. Code #include<bits/stdc++.h> #define ll long lo ...

  10. [bzoj2763][JLOI2011]飞行路线——分层图最短路

    水题.不多说什么. #include <bits/stdc++.h> using namespace std; const int maxn = 10010; const int maxk ...

随机推荐

  1. Linux操作系统常用命令合集——第六篇-压缩和归档操作(16个命令)

    1.gzip [命令作用] 压缩和解压缩文件 gzip/guzip/zcat zcat:不显式展开的前提下查看文本文件内容 zdiff/zgrep/zless/zmore [命令语法]  gzip   ...

  2. loj 2011

    对于第 $i$ 天的询问前 $i - c - 1$ 天都会影响答案主席树维护 #include <iostream> #include <cstdio> #include &l ...

  3. 数据结构实验之查找三:树的种类统计(SDUT 3375)

    C: #include <stdio.h> #include <stdlib.h> #include <string.h> struct node { char d ...

  4. Ubuntu上配置vtk开发环境——基于visual studio code 与 gcc

    环境说明 vtk版本7.1.1 visual studio 1.16.1 Ubuntu 16.04 + 自带的gcc 编译过程与windows下类似还好,运行自己的代码开始面对cmake与make的各 ...

  5. ros topic 命令

    #查看topic频率rostopic hz /xxx_imu_driver/imu #查看topic信息rostopic info /xxx_imu_driver/imu #查看topic数据rost ...

  6. vue.js 中this.$router.push()的使用

    在vue项目中,跳转可以用router-link直接跳到某个页面 因为有时候会需要做一些判断等情况,所以要用到 this.$router.push() 因为外链跳转根本就不在router的设计考虑范围 ...

  7. java集合类型源码解析之PriorityQueue

    本来第二篇想解析一下LinkedList,不过扫了一下源码后,觉得LinkedList的实现比较简单,没有什么意思,于是移步PriorityQueue. PriorityQueue通过数组实现了一个堆 ...

  8. LC 989. Add to Array-Form of Integer

    For a non-negative integer X, the array-form of X is an array of its digits in left to right order.  ...

  9. SQL-W3School-函数:SQL COUNT() 函数

    ylbtech-SQL-W3School-函数:SQL COUNT() 函数 1.返回顶部 1. COUNT() 函数返回匹配指定条件的行数. SQL COUNT() 语法 SQL COUNT(col ...

  10. [Java复习] 多线程 并发 JUC 补充

    线程安全问题? 当多个线程共享同一个全局变量,做写的操作时,可能会受到其他线程的干扰.读不会发生线程安全问题. --  Java内存模型. 非静态同步方法使用什么锁? this锁 静态同步方法使用什么 ...