NC14700 追债之旅(单源最短路问题)

题目链接

题意:
小 明 要 追 讨 债 务 小明要追讨债务
共 有 n 个 城 市 , m 条 路 共有n个城市,m条路 nm
小 明 在 1 城 , 欠 债 人 在 n 城 小明在1城,欠债人在n城 1n
小 明 经 过 一 条 路 需 要 花 掉 路 飞 , 欠 债 人 第 i 天 会 挥 霍 a i 的 钱 小明经过一条路需要花掉路飞,欠债人第i天会挥霍a_i的钱 iai
小 明 想 要 这 些 花 费 总 和 最 少 小明想要这些花费总和最少
求 这 个 最 小 值 求这个最小值
题解:
n < = 1000 n<=1000 n<=1000
所 以 直 接 考 虑 维 护 天 数 和 位 置 的 迪 杰 斯 特 拉 变 形 所以直接考虑维护天数和位置的迪杰斯特拉变形
对 于 每 次 , 花 费 不 仅 需 要 加 上 当 前 这 条 路 的 花 费 对于每次,花费不仅需要加上当前这条路的花费
还 有 加 上 欠 债 人 第 i 天 的 花 费 还有加上欠债人第i天的花费 i
用 优 先 队 列 维 护 天 数 , 位 置 和 最 小 花 费 用优先队列维护天数,位置和最小花费
直 接 跑 最 短 路 即 可 直接跑最短路即可
最 后 找 一 下 看 看 第 几 天 小 明 追 上 欠 债 人 是 最 优 最后找一下看看第几天小明追上欠债人是最优
都 没 追 上 即 为 − 1 都没追上即为-1 1

AC代码

/*
    Author:zzugzx
    Lang:C++
    Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};

struct node{
    int d,u,w;
    bool operator< (const node &p)const{
        return w>p.w;
    }
};
int n,m,k;
vector<pii> g[maxn];
int dis[1010][1010],a[maxn];
void dij(){
    memset(dis,inf,sizeof dis);
    dis[0][1]=0;
    priority_queue<node>q;
    q.push((node){0,1,0});
    while(!q.empty()){
        node p=q.top();
        q.pop();
        int u=p.u,d=p.d;
        if(p.w>dis[d][u])continue;
        for(auto i:g[u]){
            int v=i.fi,w=i.se;
            if(d+1<=k&&dis[d+1][v]>dis[d][u]+w+a[d+1]){
                dis[d+1][v]=dis[d][u]+w+a[d+1];
                q.push((node){d+1,v,dis[d+1][v]});
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    cin>>n>>m>>k;
    for(int i=1;i<=m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        g[u].pb(mp(v,w));
        g[v].pb(mp(u,w));
    }
    for(int i=1;i<=k;i++)cin>>a[i];
    dij();
    int ans=inf;
    for(int i=1;i<=k;i++)
        ans=min(ans,dis[i][n]);
    if(ans!=inf)cout<<ans;
    else cout<<-1;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值