图论之分层图最短路总结 与经典例题
一、分层图
分层图只是建图时有区别,但跑最短路板子都是一样的,正所谓图论最难的就是建图,只要有合适的建图方法,那么问题就很简单了。
分层图是指有很多个平行的图,各个平行的图之间有特殊的连接边。
如何更好的理解分层图呢,就想一下我们平时坐的地铁,地铁的某一条线就是一层图,有三条线就相当于有三层平行的图,每层之间通过共有的地铁站连接起来。这就是分层图。
用分层图的几种情况:
1、 有k个不同集合的边,将每个集合内的边建成一张图,再建立第k+1个图,是一个虚层,用这个虚层将这k张图连接起来。每次可以通过虚层转移到另一个集合的图中。如例1.小雨坐地铁。
2、 有k个机会使得走当前此边不花费代价或花费特殊的代价,可以建立k张相同的该图,每张图之间用有边的点连接起来,其代价是0或是特殊的值。每向下走一层,就代表用了一次机会,使得当前的路花费为0,最多可以走k次。如例2.飞行路线。
3、 有k个机会逆向行驶,我们可以建k张相同的该图,将每层图之间有边的两个点用的逆向的边连接。每向下走一层,就代表用了一次机会逆向走了一次,最多可以走k次。
二、经典例题
例1:nc26257 小雨坐地铁
思路: 这就是建分层图的第一种情况,有k条地铁线路,我们就建k张图,然后再建第k+1张虚层,将各个可以中转线路的点连接起来,并设定从虚层到地铁需要乘该线的代价,从地铁到虚层代价为0,这里的虚层就相当于地铁站,这就实现了地铁的转线。
代码解析:
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N = 510000,INF = 0x3f3f3f3f; //注意数据范围
typedef pair<int,int> PII;int e[N],ne[N],w[N],h[N],idx; //链式前向星建图
int n,m,s,t,dis[N];
bool vis[N];
priority_queue<PII,vector<PII>,greater<PII> > q; //dijkstra优先队列优化void add(int a,int b,int c) //加边函数
{e[idx] = b;ne[idx] = h[a];w[idx] = c;h[a] = idx++;
}int dijkstra(int s) //dijkstra模板
{memset(dis,INF,sizeof dis);dis[s] = 0;q.push({0,s});while(!q.empty()){int u = q.top().second;q.pop();if(vis[u])continue;vis[u] = 1;for(int i = h[u]; ~i;i = ne[i]){int v = e[i];if(dis[v] > dis[u]+w[i]){dis[v] = dis[u]+w[i];q.push({dis[v],v});}}}
}int main()
{int price,ad,num,pre,cur;cin >> n >> m >> s >> t;memset(h,-1,sizeof h);for(int i = 1;i <= m;i++){cin >> price >> ad >> num;for(int j = 0;j < num;j++){cin >> cur;if(j){add((i-1)*n+pre,(i-1)*n+cur,ad); //最重要的建图,k张图不需要单开k个数组建图,只需要每总点数n分成一层,类似于手动用一维数组模拟二维数组add((i-1)*n+cur,(i-1)*n+pre,ad); //同一线路的每站之间建一个无向边}add((i-1)*n+cur,n*m+cur,0); //n*m层是虚层,点进虚层的花费是0add(n*m+cur,(i-1)*n+cur,price); //虚层进地铁的花费是该线路的费用pre = cur; //存储当前点,方便和下一个点建边}}dijkstra(n*m+s); //从虚层的起点开始跑if(dis[n*m+t] == INF) //答案是虚层的终点cout << -1 << endl;elsecout << dis[n*m+t] << endl;return 0;
}
例2:P4568 飞行路线
思路: 分层图套路,最重要的就是建图,建k张相同的该图,各层内部正常连边,各层之间建边时,建一条从上到下花费为0的边,代表免费乘坐一次。跑一遍从s到n*k+t的最短路即可。用一张洛谷大佬的图:
代码解析:
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N = 2100010,INF = 0x3f3f3f3f; //注意数据范围,经测验此题最多的边数达到了2100009
typedef pair<int,int> PII;int n,m,k,s,t,dis[N];
int e[N],ne[N],w[N],h[N],idx; //链式前向星存图
bool vis[N];
priority_queue<PII,vector<PII>,greater<PII> > q; //dijkstra优先队列优化void add(int a,int b,int c) //加边函数
{e[idx] = b;ne[idx] = h[a];w[idx] = c;h[a] = idx++;
}void dijkstra(int s) //dijkstra模板
{memset(dis,INF,sizeof dis);dis[s] = 0;q.push({0,s});while(!q.empty()){int u = q.top().second;q.pop();if(vis[u])continue;vis[u] = 1;for(int i = h[u]; ~i;i = ne[i]){int v = e[i];if(dis[v] > dis[u]+w[i]){dis[v] = dis[u]+w[i];q.push({dis[v],v});}}}
}int main()
{int a,b,c;cin >> n >> m >> k >> s >> t;memset(h,-1,sizeof h);for(int i = 0;i < m;i++){cin >> a >> b >> c;add(a,b,c); //关键的建图,各层内部正常建边add(b,a,c);for(int j = 1;j <= k;j++) //从0到k层建k+1张图{add(j*n+a,j*n+b,c); //每层内部正常建图add(j*n+b,j*n+a,c);add((j-1)*n+a,j*n+b,0); //各层之间从上到下建边花费为0add((j-1)*n+b,j*n+a,0);}}for(int i = 0;i < k;i++)add(i*n+t,(i+1)*n+t,0); //为防止使用小于k次权力就到达终点,在每层的终点间建花费为0的边连起来dijkstra(s); //从起点s出发cout << dis[n*k+t] << endl; //到k层的终点为答案return 0;
}
图论之分层图最短路总结 与经典例题相关推荐
- 图论 ---- E. Minimum Path(分层图最短路 用分层图对边权操作进行选择)
题目链接 题目大意: 两点间最短路的定义变成:所有的边之和−max+min所有的边之和-max+min所有的边之和−max+min 解题思路: 这里很明显就是变成了最短路的时时候就是把路径上边权最小值 ...
- BZOJ2662[BeiJing wc2012]冻结——分层图最短路
题目描述 "我要成为魔法少女!" "那么,以灵魂为代价,你希望得到什么?" "我要将有关魔法和奇迹的一切,封印于卡片之中„„" ...
- 洛谷 - P4009 汽车加油行驶问题(分层图最短路/最小费用最大流)
题目链接:点击查看 题目大意:给出一个n*n的矩阵表示道路,途中有一些加油站,现在要从点(1,1)到达点(n,n),问最小花费,其中的一些规则如下: 汽车只能沿着网格边行驶,装满油后可以行驶K条边,出 ...
- POJ - 3662 Telephone Lines(分层图最短路)
题目链接:点击查看 题目大意:在郊区有N座通信基站,P条双向电缆,第i条电缆连接基站Ai和Bi.特别的,1号基站是通信公司的总站,N号基站位于一座农场中.现在,农场主希望对通信线路进行升级,其中升级第 ...
- codeforces1473 E.Minimum Path(分层图最短路)
E - Minimum Path 分层图最短路 第一个分层图 第0层就是按照题中给的点连边,从第0层到第1层我们连一条边权是0的边,从第1层到第2层连一条边权是原先边权2倍的边,当然第1层以及第2层之 ...
- 【bzoj2834】回家的路 分层图最短路
题目描述 输入 输出 样例输入 2 1 1 2 1 1 2 2 样例输出 5 题解 分层图最短路 dis[i][0]表示到i为横向时起点到i的最短路,dis[i][1]表示到i为纵向时起点到i的最短路 ...
- 【算法练习】CodeVs1391 伊吹萃香(分层图最短路)
题意 在幻想乡,伊吹萃香是能够控制物体密度的鬼王.因为能够控制密度,所以萃香能够制造白洞和黑洞,并可以随时改变它们.某一天萃香闲着无聊,在妖怪之山上设置了一些白洞或黑洞,由于引力的影响,给妖怪们带来了 ...
- Loj#6223 Luogu P4009 汽车加油行驶 分层图最短路
这是本蒟蒻博客的第一篇文章,不规范之处敬请各位大佬指正和谅解orz Loj#6223+Luogu P4009 文章目录 前言 一.建模 二.代码实现 1.节点在图中的编号(分层图的存储) 2.建边 对 ...
- HDU 5669 Road(线段树建树)(分层图最短路)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5669 [分析]线段树建树+分层图最短路 #include <cstdio> #includ ...
最新文章
- Laravel安装后没有vendor文件夹
- ndarray 与 array 的区别 关系,所以ndarray是一个类对象,而array是一个方法
- PCB雕刻钻孔机制作
- java jsch 密钥登陆_我们可以使用JSch进行基于SSH密钥的通信吗?
- neo4j 连接java
- 2_7 FlyweightMode 享元模式
- Exception handling 笔记
- ONOS系统架构演进,实现高可用性解决方案
- 在JAXB解组期间应用名称空间
- Sharepoint学习笔记—DebugTroubleShooting--不同调试对象的Attach方式
- rank,dense_rank,row_number使用和区别
- Asp.net Ajax Control Toolkit设计编程备忘录(色眼窥观版)——第5回(错不了专辑)
- 【报告分享】中科院-地球大数据支撑可持续发展目标报告.pdf
- 聊聊springcloud的GatewayControllerEndpoint
- 数字化中台前导--企业架构TOGAF简介
- 家用无线路由器WDS初始化失败解决方法
- 2020北京邮电大学计算机学院复试经验分享
- sap crm行业解决方案_培训机构行业crm系统解决方案
- 2022-2028全球婴儿护理台行业调研及趋势分析报告
- 北航信息与通信工程方向保研面试题集