分层图(图解+例题)

news/2024/7/15 18:06:00 标签: 图论, 算法, 数据结构

分层图

分层图多用于求最短路径,但是最短路径中可以有k条边的权值为0。

既然可以k条边为0,那么对于k条边的选取就是个问题。
所以有了分层图的概念。

对于每个点都可以选择下一条边是否赋予权值为0,那么我们就可以将图画出k+1层。

图例

我们简单画一下一个有向图,并且k=1(有一条边权值可以为0)

在这里插入图片描述
(这是初始情况,接下来我们分层)
k=1,我们要分k+1层

我们模拟从0开始,0可以走的路路径
在这里插入图片描述

我们可以看到,如果走同一层,那么权值就要+5或这+100,如果向上一层走那么要加上权值0,并且k减减,也就是每次移动可以消耗免费次数和不消耗免费次数这两种情况可以选择!

那么剩下的情况大家可以手动画一下。

代码实现

我们可以将dis数组开成二维dis[i][j]表示到达i号结点,用了j次免费操作!
比如dis[2][0]表示到达2号结点,没有用免费操作,也就是在第一层图移动。
比如dis[2][3],到达2号结点用了3次免费操作,那么下一次移动应该在第3/4层图进行!

注意理解上述操作!

接下来是一道例题,大家可以动手完成。(我用的是dijkstra+优先队列优化,完成k次免费的最短路径问题)

飞行路线

#include <bits/stdc++.h>

using namespace std;
const int maxn=1e4+10;
int dis[maxn][15],vis[maxn][15],head[maxn];
int n,m,k,sum;
int start,last;
struct node
{
    int id,v,used;//used使用了几次免费券
    node() {}
    node(int id,int v,int used):id(id),v(v),used(used) {}
    bool  operator <(const node b) const
    {
        return v>b.v;
    }
};
//链式前向星构图
struct edge
{
    int to,next,w;
} edge[maxn<<1];

void add(int u,int v,int w)
{
    edge[++sum].to=v;
    edge[sum].next=head[u];
    edge[sum].w=w;
    head[u]=sum;
}

void dijkstra(int start)
{
    memset(dis,0x7f7f7f7f,sizeof(dis));
    priority_queue<node> q;
    q.push(node(start,0,0));
    dis[start][0]=0;
    while(!q.empty())
    {
        node t=q.top();
        q.pop();
        int u=t.id;
        int kk=t.used;
        if(vis[u][kk])continue;
        vis[u][kk]=1;
        for(int i=head[u]; i; i=edge[i].next)
        {
            int v=edge[i].to;
            int w=edge[i].w;
            //两种情况,用免费和不用免费
            //不用
            if(dis[v][kk]>dis[u][kk]+w)
            {
                dis[v][kk]=dis[u][kk]+w;
                q.push(node(v,dis[v][kk],kk));
            }
            //用免费券
            if(kk+1<=k&&dis[v][kk+1]>dis[u][kk]+0)
            {
                dis[v][kk+1]=dis[u][kk];
                q.push(node(v,dis[v][kk+1],kk+1));
            }
        }
    }
}


int main()
{
    scanf("%d%d%d",&n,&m,&k);
    scanf("%d%d",&start,&last);
    for(int i=1; i<=m; i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
    }
    dijkstra(start);
    int ans=0x7f7f7f7f;
    for(int i=0;i<=k;i++)
    {
        ans=min(ans,dis[last][i]);
    }
    printf("%d\n",ans);
    return 0;
}

如果对你有帮助多多点赞支持!


http://www.niftyadmin.cn/n/860350.html

相关文章

整数奇偶排序(信息学奥赛一本通-T1181)

【题目描述】 给定10个整数的序列&#xff0c;要求对其重新排序。排序要求: 奇数在前&#xff0c;偶数在后&#xff1b; 奇数按从大到小排序&#xff1b; 偶数按从小到大排序。 【输入】 输入一行&#xff0c;包含10个整数&#xff0c;彼此以一个空格分开&#xff0c;每个整数的…

Java将日期格式化成数组年月日的格式

/*** 格式化日期为 年 月 日* * param date* return [年 月 日]*/protected static String[] formatDate(Date date) {String[] s new String[3];Calendar c Calendar.getInstance();if (date null)date new Date();c.setTime(date);s[0] String.valueOf(c.get(Calendar.Y…

Abbott的复仇(ACM/ICPC World Finals)-刘汝佳紫书

题目连接 题意分析: 简单来说这是一道走迷宫的题目,但是不一样的地方是这道题多了一个"朝向问题",每当以不同"朝向"进入一个点,它的转向也是不同的!比如1 2 WLF,代表第一行第一列,朝向西进入该点,在该点可以左转,或者直走一步到下一个点,所以每次的"…

多叉树(左孩子右兄弟)详细实现

多叉树定义 有一个根节点多个孩子结点(不止2个孩子结点) 相比于二叉树,只需要写一个结构体,在结构体中添加parent,left,right就可以表示整颗树,但是多叉树有多个孩子结点,无法仅用左右孩子做到! 怎么做呢? 我们利用"左孩子""右兄弟"的定义方法实现多叉树!…

EChart如何实现中国地图和省份下钻

由于项目需要&#xff0c;做一个地图相关的需求研究了一波&#xff0c;分享出来&#xff0c;希望对大家有所帮助 效果图如下&#xff1a; 代码如下&#xff1a; 前台jsp代码 <% page language"java" contentType"text/html; charsetutf-8"%> <%…

二叉树相关操作大全

描述二叉树 通常我们用一个结构体,来描述二叉树,这样比数组更加方便,可以直接调用左右孩子,以及父亲结点 相关代码: struct node {int p,l,r;//父亲结点,左孩子,右孩子 } T[30];//存放node结点数组结点深度 在求结点深度时,我们通常用一个D[i]数组表示结点深度,然后从根节点递…

树的重建--(根据前序遍历和中序遍历推出后序遍历)

Preorder:前序遍历是按照根–>左子树–>右子树的顺序进行递归遍历 Inorder:中序遍历是按照左子树–>根–>右子树的顺序进行遍历 Posorder:后序遍历是按照左子树–>右子树–>根的顺序进行遍历 现在给出一个树的前序遍历和中序遍历,如何推出树的后序遍历呢?…

使用idea导入maven项目后无法从阿里云仓库下载jar包的问题

今天碰到使用idea工具下载maven项目无法importjar包发现可以通过这种方式解决。记录下供大家参考。 只需要配置“-Dmaven.wagon.http.ssl.insecuretrue -Dmaven.wagon.http.ssl.allowalltrue”即可