ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NC 追债之旅 (dijkstra+分层图)

2020-08-07 21:00:27  阅读:234  来源: 互联网

标签:const int NC 追债 花费 dijkstra maxn ans dis


题意:给一张n个节点,m条双向边的图,每条边具有花费,每一天走一条边,每一天也具有花费。
问小明从1号结点到n号结点k天之内能否到达,能到达输出最小花费,否则输出-1。
解法:一开始没有想到建分层图,直接dijkstra贪心走最小花费,但是会出现一个问题,就是
到达一个结点的最小花费,会被其他路径天数并不匹配的路径所利用,从而得到答案错误。
hack数据:
4 4 2
1 2 1
1 3 1000
2 3 5
3 4 4999
0 1
如果没建分层图,1-2-3的最短花费先被更新为7,1-3-4这条路径中3-4这一次更新会利用1-2-3的最小花费更新到4的路径,导致答案错误。
所以为了避免这种天数不匹配的情况,需要分层建图,或则dis数组多开一维记录信息。dis[i][j]表示到达i结点路径长为j的最小花费
这样转移就不会出现天数不匹配的情况。

#include <bits/stdc++.h>
typedef long long ll ;
//#define int ll
int quickpow(int a , int b , int mo){int ans = 1 ;while(b){ if(b&1){ans = ans * a % mo ;}b >>= 1 ;a = a * a % mo ;}return ans ;}
using namespace std ;
#define INF 0x3f3f3f3f
const double PI = acos(-1.0);
const int maxn = 1e4+9;
const int mod = 1e9+7;
int n , m , k ;
int dis[maxn][20];
bool vis[maxn][20];
int da[maxn];
vector<pair<int , int>>g[maxn];
struct node{
    int u , w , t ;
    bool operator < (const node e) const{
        return w > e.w;
    }
    node(int _u , int _w , int _t){
        u = _u , w = _w , t = _t ;
    }
};

void dijkstra(int u){
    priority_queue<node>q;
    for(int i = 1 ; i <= n ; i++){
        for(int j = 0 ; j <= k ; j++){
            dis[i][j] = INF;
            vis[i][j] = false;
        }
    }
    dis[u][0] = 0 ;
    q.push(node{u , dis[u][0] , 0});
    while(!q.empty()){
        node now = q.top() ; q.pop();
        int u = now.u , nt = now.t;
        vis[u][nt] = 1;
        if(nt >= k) continue;
        for(auto j : g[u]){
            int v = j.first , w = j.second , t = nt + 1;
            if(!vis[v][t] && dis[v][t] > dis[u][nt] + w + da[t]){
                dis[v][t] = dis[u][nt] + w + da[t];
                q.push(node{v , dis[v][t] , t});
            }
        }
    }
}
  
void Solve(){
    cin >> n >> m >> k ;
    for(int i = 1 ; i <= m ; i++){
        int u , v , w ;
        cin >> u >> v >> w ;
        g[u].push_back({v , w});
        g[v].push_back({u , w});
    }
    for(int i = 1 ; i <= k ; i++){
        cin >> da[i];
    }
    dijkstra(1);
    int ans = INF;
    for(int i = 1 ; i <= k ; i++){
        ans = min(ans , dis[n][i]);
    }
    cout << (ans == INF ? -1 : ans) << endl;
}
  
  
signed main(){
    #ifdef ONLINE_JUDGE
    #else
        freopen("D:\\c++\\in.txt", "r", stdin);
    #endif
        Solve();
}

标签:const,int,NC,追债,花费,dijkstra,maxn,ans,dis
来源: https://www.cnblogs.com/nonames/p/13455219.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有