SP338ROADS题解--最短路变式

题目链接

https://www.luogu.org/problemnew/show/SP338

分析

联想到不久前做过的一道题\(Full\) \(Tank\),感觉可以用优先队列做,于是写了\(dijsktra\)(非负权图不敢用\(SPFA\)了)

然后发现错了,想了挺久,发现它实际上是可以找\(dis\)更大的走以花费更少的钱,于是把\(vis\)数组和\(dis\)数组全去掉就A了

优先队列保证取出的距离是最短的,如果距离相同,那么钱数是最小的,所以第一次取出\(n\)时就是答案,跑得出乎意料的快

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <queue>
#define ll long long
#define ri register int
using std::min;
using std::max;
using std::priority_queue;
template <class T>inline void read(T &x){
    x=0;int ne=0;char c;
    while(!isdigit(c=getchar()))ne=c==‘-‘;
    x=c-48;
    while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
    x=ne?-x:x;return ;
}
const int maxn=10005;
const int inf=0x7fffffff;
struct Edge{
    int ne,to,dis,co;
}edge[maxn];
int h[maxn],num_edge=0;
inline void add_edge(int f,int to,int d,int co){
    edge[++num_edge].ne=h[f];
    edge[num_edge].to=to;
    edge[num_edge].dis=d;
    edge[num_edge].co=co;
    h[f]=num_edge;
}
struct Sta{
    int ver,dis,c;
    Sta(int x,int y,int z){ver=x,dis=y,c=z;}
    bool operator <(const Sta &b)const{
        return dis==b.dis?c<b.c:dis>b.dis;
    }
};
int n,m,k;
inline void dij(){
    Sta tmp=Sta{0,0,0};
    int u,v,d,val,ans=inf;
    priority_queue<Sta>q;
    while(q.size())q.pop();
    q.push(Sta(1,0,k));
    while(q.size()){
        tmp=q.top();q.pop();
        u=tmp.ver,d=tmp.dis,val=tmp.c;
        if(u==n){
            ans=d;
            break;
        }
        for(ri i=h[u];i;i=edge[i].ne){
            v=edge[i].to;
            if(val-edge[i].co>=0){
                q.push(Sta(v,d+edge[i].dis,val-edge[i].co));
            }
        }
    }
    if(ans==inf)puts("-1");
    else printf("%d\n",ans);
    return ;
}
int main(){
    int T,x,y,z,p;
    read(T);
    while(T--){
        read(k),read(n),read(m);
        num_edge=0;
        memset(h,0,sizeof(h));
        for(ri i=1;i<=m;i++){
            read(x),read(y),read(z),read(p);
            add_edge(x,y,z,p);
            //add_edge(y,x,z,p);
        }
        dij();
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Rye-Catcher/p/9648305.html

时间: 2024-10-31 04:59:50

SP338ROADS题解--最短路变式的相关文章

UVa658 It&#39;s not a Bug, it&#39;s a Feature! (最短路,隐式图搜索)

链接:http://vjudge.net/problem/UVA-658 分析:Dijkstra求隐式图最短路. 1 #include <cstdio> 2 #include <queue> 3 using namespace std; 4 5 const int maxn = 20; 6 const int maxm = 100 + 5; 7 const int INF = 1000000000; 8 9 int n, m, t[maxm], vis[1 << max

C#报表查询区域变式存储内容条件

双击调用存储的变式条件

汉诺塔问题及其变式

先盗一张图: 正常的汉诺塔问题只要把A柱的所有盘子移动到C柱就好了,可以借助B柱.实现的逻辑如下: void hanoi(int n,char a,char b,char c) { ans++; if(n==1) { cout<<a<<"->"<<c<<endl; return; } hanoi(n-1,a,c,b); cout<<a<<"->"<<c<<en

[JZOJ5279]香港记者题解--最短路图

[JZOJ5279]香港记者题解--最短路图 题目链接 过 于 暴 力 分析 有一个naiive的想法就是从1到n跑最短路,中途建图,然后在图上按字典序最小走一遍,然而·这是不行的,你这样跳不一定能跳到终点. 所以应该是在1到n的最短路图上跳,怎么求有向图短路图?你跑一遍1到n得到\(dist1[]\),n到1的最短路得到\(dist[2]\),然后从1 BFS,对于原图一条\(u\),连向\(v\)的边,若\(dis1[u]+dis2[v]+dis(u,v)\)等于1到n的最短路距离,则最短路

表维护的变式说明

标准设置指的是默认用哪个变式.里边有自定义的变式和“基本设置”变式.“基本设置”变式是点“管理员”按钮进去设置的,是所有用户都可用的. 当前设置是当前界面上正在使用哪个变式. 原文地址:https://www.cnblogs.com/sap-George/p/11198780.html

poj 1797 Heavy Transportation 【最短路Dijkstra 变式】

Heavy Transportation Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 23914   Accepted: 6355 Description Background Hugo Heavy is happy. After the breakdown of the Cargolifter project he can now expand business. But he needs a clever man

luogu题解P2502[HAOI2006]旅行--最小生成树变式

题目链接 https://www.luogu.org/problemnew/show/P2502 分析 一个很\(naive\)的做法是从\(s\)到\(t\)双向BFS这当然会TLE 这时我就有个想法就是二分套二分边下标来求得一个比值,同时排序后从小到大枚举每一条边作为最小值,同时再枚举每一条边,如果边权之比小于比值就连起来用并查集维护连通性,可是这个时间复杂度\(O(m^2 log^2m \ \alpha(n))\)过不去QAQ 然后想为什么不直接枚举每条边作为最小值,同时搞一颗以这条边为最

最短路变短了 (思维+反向djstrea)

题解:设有一条边x->y,数组dis1[i]表示从1到i的最短距离,dis2[i]表示从n到i的最短距离. 1 如果说将x->y反向之前没有经过x->y,但是反向后我经过了x,y说明找到了一个更优的路径,那么反向后的答案就是dis1[y]+dis2[x]+(x,y),如果说反向后我没有经过 x->y,那也就是说x->y正向反向对dis[n]的结果没有影响喽. 2 如果说反向之前我经过了x->y,如果反向后没有经过x->y,那么此时的最短路也一定是大于等于dis1[

P1144 最短路计数 题解 最短路应用题

题目链接:https://www.luogu.org/problem/P1144 其实这道题目是最短路的变形题,因为数据范围 \(N \le 10^6, M \le 2 \times 10^6\) ,所以直接用Dijkstra算法是不行的,可以使用 Dijkstra+堆优化 或者 SPFA算法来实现. 我这里使用 SPFA算法 来实现 (不会Dijkstra堆优化囧) 这道题目因为需要计数,所以需要在dist数组基础上再开一个cnt数组,其含义如下: \(dist[u]\) :起点 \(1\)