您的位置:首页 > 其它

Vijos1901 学姐的钱包

2016-11-11 21:08 232 查看

 

描述

学姐每次出门逛街都要带恰好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即可。    
/*by SilverN*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#define LL long long
using namespace std;
const int mxn=400010;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct edge{
int v,nxt,dis;
}e[mxn<<2];
int hd[mxn],mct=0;
void add_edge(int u,int v,int dis){
e[++mct].v=v;e[mct].dis=dis;e[mct].nxt=hd[u];hd[u]=mct;
return;
}
//
struct node{
int val,id;
}a[mxn];
int cmp(const node a,const node b){
return a.val<b.val;
}
map<int,int>mp;
int id=0;
int T;
int n,m;
int u[mxn],v[mxn],d[mxn];
queue<int>q;
bool inq[mxn];
LL dis[mxn];LL INF;
void SPFA(int st){
memset(dis,0x3f,sizeof dis);
INF=dis[0];
while(!q.empty()) q.pop();
q.push(st);
inq[st]=1;
dis[st]=0;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=hd[u];i;i=e[i].nxt){
int v=e[i].v;
if(dis[v]>dis[u]+e[i].dis){
dis[v]=dis[u]+e[i].dis;
if(!inq[v]){
inq[v]=1;
q.push(v);
}
}
}
inq[u]=0;
}
return;
}
void init(){
memset(e,0,sizeof e);
memset(hd,0,sizeof hd);
memset(inq,0,sizeof inq);
mct=id=0;
mp.clear();
return;
}

int main(){
freopen("10.in","r",stdin);
T=read();
int i,j;
int cas=0;
while(T--){
init();
n=read();m=read();
mp[m]=++id;
a[id].val=m;a[id].id=id;
for(i=1;i<=n;i++){
u[i]=read();v[i]=read();d[i]=read();
if(u[i]>m)u[i]=m;
if(v[i]>m)v[i]=m;
if(!mp[u[i]]){
mp[u[i]]=++id;
a[id].id=id;
a[id].val=u[i];
}
if(!mp[v[i]]){
mp[v[i]]=++id;
a[id].id=id;
a[id].val=v[i];
}
add_edge(mp[v[i]],mp[u[i]],d[i]);
}
sort(a+1,a+id+1,cmp);
for(i=2;i<=id;i++){
add_edge(a[i].id,a[i-1].id,0);
}
LL ans;
if(a[1].val==1){
SPFA(a[1].id);ans=dis[mp[m]];
}
else ans=-1;
if(ans>=INF)ans=-1;
printf("Case #%d: %lld\n",++cas,ans);
}
return 0;
}

 

 

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: