In each exchange, one can exchange for an item of Vi yuan if he (she) has an item values more than or equal to Ri yuan, with a time cost of Ti minutes.
Now, you task is help the star to exchange for an item which values more than or equal to M yuan with the minimum time.
The first line of the input is T (no more than 20), which stands for the number of test cases you need to solve.
For each case, two integers N, M (1 <= N <= 10^5, 1 <= M <= 10^9) in the first line indicates the number of available exchanges and the expected value of final item. Then N lines follow, each line describes an exchange with 3 integers Vi, Ri, Ti (1 <= Ri <= Vi <= 10^9, 1 <= Ti <= 10^9).
For every test case, you should output "Case #k: " first, where k indicates the case number and counts from 1. Then output the minimum time. Output “-1” if no solution can be found.
3 10
5 1 3
8 2 5
10 9 2
4 5
2 1 1
3 2 1
4 3 1
8 4 1
5 9
5 1 1
10 4 10
8 1 10
11 6 1
7 3 8
Case #2: 4
Case #3: 10
//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const long long max_int=((long long)1<<63)-1;
const long long min_int=((long long)1<<63);
const int maxn=313405;
//从1开始
struct node
{
long long left,right,maxn,minc;
};
node tree[maxn*3];//构造线段树
int n;//点数
long long nmax,nmin;//当前最大值和最小者,查询是用
void buildtree(int id,int l,int r)//建树
{
tree[id].left=l;tree[id].right=r;//初始化左右端点
tree[id].maxn=min_int;tree[id].minc=max_int;//初始化最大,小值
if(l!=r)//是根节点
{
buildtree(2*id,l,(l+r)/2);//左子树
buildtree(2*id+1,(l+r)/2+1,r);//右子树
}
}
void insert(int id,int i,long long val)
{
if(tree[id].left==i&&tree[id].right==i)//叶子节点
{
tree[id].minc=tree[id].maxn=val;
return ;
}
tree[id].maxn=max(tree[id].maxn,val);//更新次节点的最大值
tree[id].minc=min(tree[id].minc,val);//更新次节点的最小值
if(i<=(tree[id].left+tree[id].right)/2) insert(2*id,i,val);//进去左子树
else insert(2*id+1,i,val);//进去右子树
}
void query(int id,int s,int e)//查询
{
if(tree[id].maxn<=nmax&&tree[id].minc>=nmin) return ;//剪枝
if(tree[id].left==s&&tree[id].right==e)//叶子节点
{
nmin=min(tree[id].minc,nmin);
nmax=max(tree[id].maxn,nmax);
return ;
}
if(e<=(tree[id].left+tree[id].right)/2)//左子树
{
query(2*id,s,e);
}
else if(s>=(tree[id].left+tree[id].right)/2+1)//右子树
{
query(2*id+1,s,e);
}
else//横跨左右子树
{
query(2*id,s,(tree[id].left+tree[id].right)/2);//左
query(2*id+1,(tree[id].left+tree[id].right)/2+1,e);//右
}
}
struct edge
{
int t,w;//u->t=w;
int next;
};
int V,E;//点数(从1开始),边数
int p[maxn];//邻接表原图
edge G[maxn];//邻接表原图
int l;
void init()
{
V=0;
memset(p,-1,sizeof(p));
l=0;
}
void addedge(int u,int t,int w,int l)
{
G[l].w=w;
G[l].t=t;
G[l].next=p[u];
p[u]=l;
}
long long ha[maxn];
void ihash()
{
memset(ha,-1,sizeof(ha));
}
int hash(int u)
{
int ret=u%maxn;
while(ha[ret]!=-1&&ha[ret]!=u) ret=(ret+1)%maxn;
ha[ret]=u;
return ret;
}
long long tmp[maxn];
int tp;
long long pos[maxn];
void ilsh()
{
tp=0;
}
void lsh()//从0开始
{
sort(tmp,tmp+tp);
V=unique(tmp,tmp+tp)-tmp;
for(int i=0;i<V;i++)
{
pos[hash(tmp[i])]=i;
}
}
long long u[maxn],v[maxn],w[maxn];
long long goal;
long long d[maxn];
int main()
{
long long ci,pl=1;cin>>ci;
while(ci--)
{
init();
ihash();
ilsh();
cin>>E>>goal;
tmp[tp++]=1;
for(long long i=0;i<E;i++)
{
cin>>u[i]>>v[i]>>w[i];
tmp[tp++]=u[i];
tmp[tp++]=v[i];
}
lsh();
for(long long i=0;i<E;i++)
{
addedge(pos[hash(u[i])],pos[hash(v[i])],w[i],l++);
}
d[0]=0;
for(long long i=1;i<V;i++) d[i]=max_int;
n=V;
buildtree(1,1,n);//从1开始
insert(1,1,0);
for(int i=1;i<V;i++)
{
for(int j=p[pos[hash(tmp[i])]];j!=-1;j=G[j].next)
{
int t=G[j].t;
long long val=G[j].w;
nmax=min_int;nmin=max_int;
query(1,t+1,i);//从1开始
if(nmin!=max_int) d[i]=min(d[i],nmin+val);
}
if(d[i]!=max_int) insert(1,i+1,d[i]);
}
long long ans=max_int;
for(int i=0;i<V;i++)
{
if(tmp[i]>=goal) ans=min(ans,d[i]);
}
if(ans!=max_int) cout<<"Case #"<<pl++<<": "<<ans<<endl;
else cout<<"Case #"<<pl++<<": -1"<<endl;
}
return 0;
}