图论、贪心、最短路

想复杂了。

由于坐车任何时候都比走路快,所以能坐车的时候一定是坐车的。

令 $dis_i$ 为从 $i$ 出发在时限内到达 $n$ 的最晚出发时间,从 $n$ 开始跑最短路,如果能够坐车扩展到下一节点则坐车,否则在走路和原地等待中取较优决策扩展到下一节点。

由于 $n,m$ 同阶,时间复杂度 $O(n \log n)$。

#include<bits/stdc++.h>
using namespace std;
constexpr long long inf=1'000'000'000'000'000'000ll;
struct Edge{
    int to;long long dis;
    Edge(int x,long long y):to(x),dis(y){}
    bool operator<(const Edge &x)const{
        return this->dis>x.dis;
    }
};
struct Star{int w,v,to;Star(int x,int y,int z):w(x),v(y),to(z){}};
long long E,L,R,dis[100'005];
vector<Star> v[100'005];
bool on[100'005];
int n,m;
void solution(){
    cin>>n>>m>>E>>L>>R;
    for(int i=1;i<=n;i++) on[i]=0,dis[i]=inf,v[i].clear();
    for(int i=1;i<=m;i++){
        static int x,y,l,r;
        cin>>x>>y>>l>>r;
        v[x].push_back(Star(l,r,y));
        v[y].push_back(Star(l,r,x));
    }
    dis[n]=0ll;
    priority_queue<Edge> q;
    q.push(Edge(n,dis[n]));
    while(!q.empty()){
        int now=q.top().to;q.pop();
        if(on[now]) continue;
        on[now]=1;
        for(auto i:v[now]){
            if(dis[now]>=E-L||dis[now]+i.w<=E-R){
                if(dis[now]+i.w<dis[i.to]){
                    dis[i.to]=dis[now]+i.w;
                    q.push(Edge(i.to,dis[i.to]));
                }
            }
            else{
                long long nxt=min(dis[now]+i.v,E-L+i.w);
                if(nxt<dis[i.to]){
                    dis[i.to]=nxt;
                    q.push(Edge(i.to,nxt));
                }
            }
        }
    }
    cout<<max(E-dis[1],-1ll)<<'\n';
}
int T;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>T;
    while(T--) solution();
    return 0;
}
最后修改:2024 年 10 月 07 日
如果觉得我的文章对你有用,请随意赞赏