bzoj2662: [BeiJing wc2012]冻结 分层图最短路

本文介绍了一种使用SPFA算法解决最短路径问题的方法,通过构建图结构并实现SPFA算法,实现了从起点到终点的最短路径求解。包括算法原理、代码实现及实例演示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

与2763相似,只是使用加速的时候距离变了一下。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
#define maxn 110000
int dis[maxn][20];
int b[maxn],next[maxn],val[maxn],p[maxn];
bool flag[maxn][30];
int n,m,num;
int st,ed,k;
struct node
{
    int id,use;
};
void build(int x,int y,int z)
{
    num++;
    b[num]=y;
    val[num]=z;
    next[num]=p[x];
    p[x]=num;
}
void spfa()
{
    memset(dis,0x3f3f3f3f,sizeof(dis));
    queue<node>q;
    node tmp,cur;
    tmp.id=st;
    tmp.use=0;
    flag[st][0]=1;
    dis[st][0]=0;
    q.push(tmp);
    while(!q.empty())
    {
        tmp=q.front();
        q.pop();
        int id=tmp.id;
        int use=tmp.use;
        flag[id][use]=0;
        for(int e=p[id];e;e=next[e])
        {
            int to=b[e];
            if(dis[to][use]>dis[id][use]+val[e])
            {
                dis[to][use]=dis[id][use]+val[e];
                if(!flag[to][use])
                {
                    flag[to][use]=1;
                    cur.id=to;
                    cur.use=use;
                    q.push(cur);
                }
            }

            if(use<k)
            {
                if(dis[to][use+1]>dis[id][use]+val[e]/2)
                {
                    dis[to][use+1]=dis[id][use]+val[e]/2;
                    if(!flag[to][use+1])
                    {
                        flag[to][use+1]=1;
                        cur.id=to;
                        cur.use=use+1;
                        q.push(cur);
                    }
                }
            }
        }
    }
    int ans=0x3f3f3f3f;
    for(int i=0;i<=k;i++)
    {
        ans=min(ans,dis[ed][i]);
    }
    printf("%d",ans);
}
int main()
{
    int x,y,z;
    scanf("%d%d%d",&n,&m,&k);
    st=1;
    ed=n;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        build(x,y,z);
        build(y,x,z);
    }
    spfa();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值