寒假集训第五天---最短路

Posted wifepi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了寒假集训第五天---最短路相关的知识,希望对你有一定的参考价值。

CodeForces - 229B Planets

题目大意:给你m条边的无向图,边权代表从一个点到另一个点的花费时间,每个点给你k个时间点,表示如果你在ki时刻到达该顶点,你需要等待一秒。问从顶点1到顶点n的最少耗时是多少。

题解:正常跑最短路,在松弛的时候判断这个点需要等待多少秒再出发。

卡点:对于一个点来说我可能等待多秒,对于起点我可能也要等待(wa7),对于每个点我不需要重复计算等待时间,我只需要计算我目前这个点要想出发我需要等待多少时间,用这个时间去松弛他所能更新的边。对于我堆优化的dijkstra来说,堆上面的点的出发时间一定小于等于我下面的点的出发时间,相当于把考虑到时间后的最短路的问题抛给了优先队列自己去选择。妙哉

代??

技术图片
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
int cnt = 0 ;
const int maxn = 1e5 + 10 ;
const int inf = 0x3f3f3f3f ;
#define ll long long
ll MAX ;
int head[maxn] ;
int vis[maxn] ;
int dis[maxn] ;
vector<int> ve[maxn] ;
int n, m, k ;
struct Edge
{
    int from, to, dist, next ;
}edge[maxn<<1] ;
void add(int from, int to, int dist)
{
    ++ cnt ;
    edge[cnt].from = from ;
    edge[cnt].to = to ;
    edge[cnt].dist = dist ;
    edge[cnt].next = head[from] ;
    head[from] = cnt ;
}
struct node
{
    int index, dist ;
    bool operator < (const node &x)const
    {
        return dist > x.dist ;
    }
};
priority_queue<node> q ;
int main(int argc, char const *argv[])
{
    memset(head,0,sizeof head) ;
    memset(vis,0,sizeof vis) ;
    scanf("%d %d",&n,&m) ;
    for(int i = 1, from, to, dist ; i <= m ; ++ i)
    {
        scanf("%d %d %d",&from,&to,&dist) ;
        add(from,to,dist) ;
        add(to,from,dist) ;
    }
    for(int i = 1, tt, tmp ; i <= n ; ++ i)
    {
        scanf("%d",&tt) ;
        for(int j = 0 ; j < tt ; ++ j)
        {
            scanf("%d",&tmp) ;
            ve[i].push_back(tmp) ;
        }
    }
    for(int i = 1 ; i <= n ; ++ i) dis[i] = inf ;
    int pos = lower_bound(ve[1].begin(),ve[1].end(),0) - ve[1].begin() ;
    while(pos < ve[1].size() && pos == ve[1][pos]) ++ pos ;
    dis[1] = pos ;
    q.push(node{1,0}) ;
    while(!q.empty())
    {
        node x = q.top() ;
        q.pop() ;
        int u = x.index ;
        if(vis[u]) continue ;
        vis[u] = 1 ;
        int tmp = 0 ;
        int pos = lower_bound(ve[u].begin(),ve[u].end(),dis[u]) - ve[u].begin() ;
        while(pos < ve[u].size() && ve[u][pos] == dis[u] + tmp) ++ tmp, ++ pos ;
        for(int i = head[u] ; i ; i = edge[i].next)
        {
            if(dis[edge[i].to] > dis[u] + edge[i].dist)
            {
                if(dis[edge[i].to] > dis[u] + edge[i].dist + tmp)
                {
                    dis[edge[i].to] = dis[u] + edge[i].dist + tmp ;
                    q.push(node{edge[i].to,dis[edge[i].to]}) ;
                }
            }
        }
    }
    printf("%d
",dis[n] == inf ? -1 : dis[n]) ;
    return 0;
}
View Code

以上是关于寒假集训第五天---最短路的主要内容,如果未能解决你的问题,请参考以下文章

(寒假集训) Piggyback(最短路)

(寒假集训)Roadblock(最短路)

寒假集训第六天---LCA题解

寒假每日一题回文平方(个人练习)详细题解+推导证明(第五天)

寒假集训日志——最小生成树,拓扑排序,欧拉回路,连通路

2022牛客寒假算法基础集训营6 全部题解