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.

看到这题,觉得可以用类似差分约束的办法建图跑SPFA,然而写起来有些无力。

查了一发题解,看别人是怎么写的,第一眼看到的是隔壁阿当学长的线段树DP,第二眼看到的是隔壁OrionRigel的神奇SPFA……害怕。

既然知道SPFA可行了,就乱搞试试看,真的搞出来了

将每一个可以到达的价值离散化(这里用了巨慢的map,最大一个点跑了1000ms),依据题中的转化关系连边。之后从大价值向小价值连一条权为0的有向边(回溯),跑SPFA即可。

  1 /*by SilverN*/
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 #include<vector>
  8 #include<queue>
  9 #include<map>
 10 #define LL long long
 11 using namespace std;
 12 const int mxn=400010;
 13 int read(){
 14     int x=0,f=1;char ch=getchar();
 15     while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
 16     while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
 17     return x*f;
 18 }
 19 struct edge{
 20     int v,nxt,dis;
 21 }e[mxn<<2];
 22 int hd[mxn],mct=0;
 23 void add_edge(int u,int v,int dis){
 24     e[++mct].v=v;e[mct].dis=dis;e[mct].nxt=hd[u];hd[u]=mct;
 25     return;
 26 }
 27 //
 28 struct node{
 29     int val,id;
 30 }a[mxn];
 31 int cmp(const node a,const node b){
 32     return a.val<b.val;
 33 }
 34 map<int,int>mp;
 35 int id=0;
 36 int T;
 37 int n,m;
 38 int u[mxn],v[mxn],d[mxn];
 39 queue<int>q;
 40 bool inq[mxn];
 41 LL dis[mxn];LL INF;
 42 void SPFA(int st){
 43     memset(dis,0x3f,sizeof dis);
 44     INF=dis[0];
 45     while(!q.empty()) q.pop();
 46     q.push(st);
 47     inq[st]=1;
 48     dis[st]=0;
 49     while(!q.empty()){
 50         int u=q.front();q.pop();
 51         for(int i=hd[u];i;i=e[i].nxt){
 52             int v=e[i].v;
 53             if(dis[v]>dis[u]+e[i].dis){
 54                 dis[v]=dis[u]+e[i].dis;
 55                 if(!inq[v]){
 56                     inq[v]=1;
 57                     q.push(v);
 58                 }
 59             }
 60         }
 61         inq[u]=0;
 62     }
 63     return;
 64 }
 65 void init(){
 66     memset(e,0,sizeof e);
 67     memset(hd,0,sizeof hd);
 68     memset(inq,0,sizeof inq);
 69     mct=id=0;
 70     mp.clear();
 71     return;
 72 }
 73
 74 int main(){
 75     freopen("10.in","r",stdin);
 76     T=read();
 77     int i,j;
 78     int cas=0;
 79     while(T--){
 80         init();
 81         n=read();m=read();
 82         mp[m]=++id;
 83         a[id].val=m;a[id].id=id;
 84         for(i=1;i<=n;i++){
 85             u[i]=read();v[i]=read();d[i]=read();
 86             if(u[i]>m)u[i]=m;
 87             if(v[i]>m)v[i]=m;
 88             if(!mp[u[i]]){
 89                 mp[u[i]]=++id;
 90                 a[id].id=id;
 91                 a[id].val=u[i];
 92             }
 93             if(!mp[v[i]]){
 94                 mp[v[i]]=++id;
 95                 a[id].id=id;
 96                 a[id].val=v[i];
 97             }
 98             add_edge(mp[v[i]],mp[u[i]],d[i]);
 99         }
100         sort(a+1,a+id+1,cmp);
101         for(i=2;i<=id;i++){
102             add_edge(a[i].id,a[i-1].id,0);
103         }
104         LL ans;
105         if(a[1].val==1){
106             SPFA(a[1].id);ans=dis[mp[m]];
107         }
108         else ans=-1;
109         if(ans>=INF)ans=-1;
110         printf("Case #%d: %lld\n",++cas,ans);
111     }
112     return 0;
113 }
时间: 2024-10-12 16:06:41

Vijos1901 学姐的钱包的相关文章

Vijos1901学姐的钱包

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

vijosP1901学姐的钱包

题目:https://vijos.org/p/1901 题解:这题比较有意思. 经过一番思考之后我想出了下面的算法: 我们反着来推,按i从大到小 f[i]表示从>=m到 i 需要多长时间,则如果v[j]=i,则我们可以用f[i]+t[j] 去更新 r[j]-inf 的所有f值 由于f[i]是一个单调递减的函数,则我们只需要用它去更新r[j]-i-1即可 然后问题就变成了区间修改,单点查询,线段树即可 代码: 1 #include<cstdio> 2 #include<cstdlib

2014.11.12模拟赛【美妙的数字】| vijos1904学姐的幸运数字

美妙的数字(number.c/.cpp/.pas) 题目描述 黄巨大认为非负整数是美妙的,并且它的数值越小就越美妙.当然0是最美妙的啦. 现在他得到一串非负整数,对于每个数都可以选择先对它做二进制非运算(模二意义下0.1互换,注意前导0也要交换),然后在任意相邻的两个数之间插入二进制与.二进制或,或者二进制异或.现在他想知道这样计算完产生的最美妙的数字是多少. 一共T组数据.对于每组数据,第一行一个n,表示这组数据中一串数有多少个.下面n个非负整数,表示这串数. 样例输入 2 2 3 6 3 1

卿学姐与魔法(优先队列)

个人心得:思路很简单,不过就是会超时,而且直接用数组的话肯定不够大. 所以就用优先队列,让里面只装N个数就好了,然后再次添加时进行比较,比他小就放进去. 不过这样超时,所以先将A,B排序,然后只要比队首大就break就可以过了. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<queue> 6 #include<

A - 卿学姐与公主(线段树+单点更新+区间极值)

A - 卿学姐与公主 Time Limit: 2000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 某日,百无聊赖的卿学姐打开了某11区的某魔幻游戏 在这个魔幻的游戏里,生活着一个美丽的公主,但现在公主被关押在了魔王的城堡中. 英勇的卿学姐拔出利刃冲向了拯救公主的道路. 走过了荒野,翻越了高山,跨过了大洋,卿学姐来到了魔王的第一道城关. 在这个城关面前的是魔王的精锐部队,这些士兵

qwb与学姐 (带秩并查集)

qwb与学姐 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 149  Solved: 54[Submit][Status][Web Board] Description qwb打算向学姐表白,可是学姐已经受够了他的骚扰,于是出了一个题想难住他:已知一幅n个点m条边的无向图,定义路径的值为这条路径上最短的边的长度,现在有 k个询问,询问从A点到B点的所有路径的值的最大值.qwb听完这个问题很绝望啊,聪明的你能帮帮他吗? Input 一组数据.第一行三

vijosP1903学姐的实习工资

描述 学姐去实习了, 一共实习了N天, 每一天都可以得到实习工资V[i], 这里V[1..N]被看作是整数序列.因为学姐很厉害, 所以V[1..N]是不下降的.也就是说学姐每天的工资只会越来越多, 不会变少.然而遗憾的是, 偷懒的学姐只记下来了其中M天的收入.第A[1]天获得了的工资为B[1].第A[2]天获得了的工资为B[2].第A[3]天获得了的工资为B[3]....第A[M]天获得了的工资为B[M].其中A[]是递增的.好在她记下来了第一天和第N天的收入. 也就是说A[1]=1, A[M]

qwb与学姐

qwb与学姐 Time Limit: 1 Sec  Memory Limit: 128 MB Description qwb打算向学姐表白,可是学姐已经受够了他的骚扰,于是出了一个题想难住他:已知一幅n个点m条边的无向图,定义路径的值为这条路径上最短的边的长度,现在有 k个询问,询问从A点到B点的所有路径的值的最大值.qwb听完这个问题很绝望啊,聪明的你能帮帮他吗? Input 一组数据.第一行三个整数n,m,k (1<=N<=50000,m<=200000,k<=100000).

hdu1344卿学姐种美丽的花

地址:http://acm.uestc.edu.cn/#/problem/show/1344 题目: 卿学姐种美丽的花 Time Limit: 8000/4000MS (Java/Others)     Memory Limit: 125535/65535KB (Java/Others) Submit Status 众所周知,在喵哈哈村,有一个温柔善良的卿学姐. 卿学姐喜欢和她一样美丽的花.所以卿学姐家的后院有很多的花坛. 卿学姐有nn个花坛,一开始第ii个花坛里有A[i]A[i]朵花.每过一段