The Shortest Path in Nya Graph(图论,最短路,建图)

题意:有一个双向图,上面的点多了一个属性:层数。一个点除了能走到与它链接的点,还能走到相邻的层数上的任意一个点,这种操作也需要成本。让你求最短路。

难点:建图。
在普通最短路问题的基础上,就多了层数的限制。 那么设每个点a都有一个“中转点ax”,这个点到中转点的成本为0。而且这个点的中转点ax相邻的中转点ax+1、ax-1到a的成本是cb。以这个理论建图,就可以得到如下代码。

 for (int i=1;i<=n;i++)
        {//中转点+(n+1)是为了不和i冲突
            operation(n+Ceng[i],i,0);//只能建立单向图,如果建立双向图会导致同一层上的边权为0
            operation(i,n+Ceng[i]-1,cb);
            operation(i,n+Ceng[i]+1,cb);
        }

这里的Ceng储存的是第i个点的层数,operation函数是将点放入链式向前星。

然后要考虑的问题有n、m都是1E5的。所以我使用SPFA+链式向前星。好像也可以用优先队列优化的Dijsktra,但我tcl不会优先队列优化。哭唧唧。

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn=4E5+5;
const int INF=1<<30;
struct node
{
    int next,to,val;
}qwe[maxn<<1];
int d[maxn];
bool vis[maxn];
int head[maxn<<1];
int Ceng[maxn];
int cnt,n,m,cb;
void operation (int a,int b,int c)
{
    qwe[cnt].next=head[a];
    qwe[cnt].to=b;
    qwe[cnt].val=c;
    head[a]=cnt++;
}
void reset ()
{
    memset(head,-1, sizeof(head));
    cnt=1;
}
void SPFA(int start)
{
    int tmp;
    memset(vis,false, sizeof(false));
    for (int i=0;i<=maxn;i++)
        d[i]=INF;
    d[start]=0;
    queue<int>q;
    q.push(start);
    vis[start]=true;
    while (!q.empty())
    {
        tmp=q.front();
        q.pop();
        vis[tmp]=false;
        for (int i=head[tmp];~i;i=qwe[i].next)
        {

            if (d[qwe[i].to]>d[tmp]+qwe[i].val)
            {
                d[qwe[i].to]=d[tmp]+qwe[i].val;
                if (vis[qwe[i].to]== false)
                {
                    q.push(qwe[i].to);
                    vis[qwe[i].to]=true;
                }
            }
        }
    }
}
int main ()
{
    int a,b, c = 0;
    int t;
    scanf ("%d",&t);
    for (int turn=1;turn<=t;turn++)
    {
        reset();
        scanf ("%d%d%d",&n,&m,&cb);
        for (int i=1;i<=n;i++)
            scanf ("%d",&Ceng[i]);
        for (int i=1;i<=n;i++)
        {
            operation(n+Ceng[i]+1,i,0);
            operation(i,n+Ceng[i],cb);
            operation(i,n+Ceng[i]+2,cb);
        }
        for (int i=1;i<=m;i++)
        {
            scanf ("%d%d%d",&a,&b,&c);
            operation(a,b,c);
            operation(b,a,c);
        }
        SPFA(1);
        printf ("Case #%d: ",turn);
        if(d[n]!=INF) printf ("%d\n",d[n]);
        else printf ("-1\n");
    }
    return 0;
}

P.S我一开始没有想到建图,而是去增加寻找最短路的方式。理所当然的TLE。

引用\[1\]提供了使用Python的networkx库绘制网络图和计算最短加权路径的示例代码。该代码使用了一个包含顶点和边的列表,并使用add_nodes_from和add_weighted_edges_from方法将它们添加到图中。然后,使用nx.shortest_path_length方法计算了从顶点v1到顶点v11的最短加权路径长度为13。\[1\] 引用\[2\]提供了一个计算最短路径的Python程序示例。该程序使用了numpy和networkx库。首先,定义了一个包含顶点和边的列表,并使用add_nodes_from和add_weighted_edges_from方法将它们添加到图中。然后,使用nx.shortest_path_length方法计算了最短路径长度,并将结果存储在一个字典中。接下来,使用numpy创建了一个6x6的零矩阵,并使用两个嵌套的for循环将最短路径长度填充到矩阵中。最后,使用矩阵乘法计算了运力,并找到了最小运力和对应的位置。\[2\] 引用\[3\]提供了关于Dijkstra算法的一些背景信息。Dijkstra算法是一种寻找最短路径的算法,适用于所有权重大于等于0的情况。它可以用于解决从一个起始点到任意一个点的最短路径问题。\[3\] 综上所述,如果你想在Python中计算图论中的最短路径,可以使用networkx库和Dijkstra算法。你可以根据引用\[1\]和引用\[2\]中的示例代码进行操作。 #### 引用[.reference_title] - *1* *3* [运筹学——图论与最短距离(Python实现)](https://blog.csdn.net/weixin_46039719/article/details/122521276)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [数学建模:图论模型 — 最短路模型示例 (Python 求解)](https://blog.csdn.net/qq_55851911/article/details/124776487)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值