spfa vijos1901 学姐的钱包

描述

学姐每次出门逛街都要带恰好M元钱, 不过她今天却忘记带钱包了.
可怜的doc只好自己凑钱给学姐, 但是他口袋里只有一元钱.
好在doc的N位朋友们都特别有钱, 他们答应与doc作一些交换.
其中第i位朋友说:
如果doc有不少于Ri元钱,
doc可以把手上所有的钱都给这位朋友,
并从这位朋友手中换回Vi元钱,
但是这次交换会浪费Ti的时间.
doc希望可以在最短的时间内换到M元钱(其实是可以大于M的, 因为doc可以存私房钱呢), 否则学姐会生气的!

格式

输入格式

输入数据第一行给定T, 表示总的询问次数.
对于每一次询问, 第一行给出两个整数N和M.
之后N行, 每一行给出三个整数Vi, Ri和Ti. (保证Ri<=Vi).

输出格式

对于每一次询问, 首先输出询问的编号, 参见样例输出.
之后输出最小需要的时间, 如果不可能完成目标, 则输出-1.

样例1

样例输入1

3
5 9
5 1 1
10 4 10
8 1 10
11 6 1
7 3 8
4 5
2 1 1
3 2 1
4 3 1
8 4 1
3 10
5 1 3
8 2 5
10 9 2

样例输出1

Case #1: 10
Case #2: 4
Case #3: -1

限制

对于40%的数据
N <= 1500.

对于100%的数据
T <= 5
1 <= N <= 100000.
1 <= M <= 1000000000.
1 <= Ri <= Vi <= 1000000000.
1 <= Ti <= 1000000000.

蒟蒻并没有看懂sdfzgxk的题解orz……

然而看到了这样一句话“用f[i]表示从大于等于m的点到i的最短时间

这……好像可以单源最短路,翻sdfzwxl的题解,可写

并不清楚long long下怎么赋极值

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 using namespace std;
 7 int t,n,m,cnt,tot;
 8 struct dt{
 9     int s,e;
10     long long v;
11 }road[200010]; 
12 struct data{
13     int next,to;
14     long long dis;
15 }edge[400010];
16 int num[400010],head[200010];
17 long long w[200010];
18 bool check[200010];
19 queue<int>q;
20 void add(int start,int end,long long dd){
21     edge[++tot].next=head[start];
22     edge[tot].to=end;
23     edge[tot].dis=dd;
24     head[start]=tot;
25 }
26 void spfa(){
27     memset(w,0x3f3f3f3f,sizeof(w));
28     check[1]=1;
29     w[1]=0;
30     q.push(1);
31     while(!q.empty()){
32         int u=q.front();
33         q.pop();
34         check[u]=0;
35         for(int i=head[u];i;i=edge[i].next)
36             if(w[edge[i].to]>w[u]+edge[i].dis){
37                 w[edge[i].to]=w[u]+edge[i].dis;
38                 if(!check[edge[i].to]){
39                     check[edge[i].to]=1;
40                     q.push(edge[i].to);
41                 }
42             }
43     }
44 }
45 int main(){
46     scanf("%d",&t);
47     for(int ii=1;ii<=t;ii++){
48         memset(head,0,sizeof(head));
49         cnt=0;
50         tot=0;
51         scanf("%d%d",&n,&m);
52         for(int i=1;i<=n;i++){
53             scanf("%d%d%lld",&road[i].s,&road[i].e,&road[i].v);
54             if(road[i].s>m) road[i].s=m;
55             if(road[i].e>m) road[i].e=m;
56             num[++cnt]=road[i].s;
57             num[++cnt]=road[i].e;
58         }
59         sort(num+1,num+cnt+1);
60         cnt=unique(num+1,num+cnt+1)-num-1;
61         for(int i=1;i<=n;i++){
62             road[i].s=lower_bound(num+1,num+cnt+1,road[i].s)-num;
63             road[i].e=lower_bound(num+1,num+cnt+1,road[i].e)-num;
64             add(road[i].e,road[i].s,road[i].v);
65         }
66         for(int i=2;i<=cnt;i++) add(i,i-1,0);
67         spfa();
68         if(w[cnt]==0x3f3f3f3f) printf("Case #%d: -1
",ii);
69         else printf("Case #%d: %lld
",ii,w[cnt]);
70     }
71     return 0;
72 }
原文地址:https://www.cnblogs.com/zwube/p/7049073.html