Description
这是一个神奇的国度。
这个国度一共有N个城市组成,让我们将他们编号为1~N,
城市与城市之间修建有发达的铁路系统,
而且不论距离有多远,乘客都只需要在入站的时候支付相应的车费,就可以沿着铁路到达另一个城市。
其中编号为i的城市所需要支付的车票为Ci元。
到达另一个城市之后,乘客只能出站,无法像地铁一样换乘。(这也叫发达?!)
这一天,chanming带着他的第一个月的工资K元来到了城市1。
他们想到城市N去寻找宝藏。
chanming用惊人的智慧发现了一个逃票的方法。并且在任何城市都可以通用。
并且第一次逃票之后,chanming将会爱上逃票的快感,
并将不会再使用钱购买车票(因为处女座的强迫症=。=)。
请问chanming最少需要逃几次票?
Input
输入数据包含多组数据。第一行是一个整数T(T<=30),表示测试数据的数量。
对于每组测试数据,第一行为三个整数,N,M,K(1<=N<=105,M<=106,K<=108),分别表示城市的数量,铁路的数量和chanming带的K元
接下来一行有N个整数,第i个表示Ci,也就是第i个城市入站的时候需要支付的车票费。
接下来M行,每行2个整数A,B(1<=A,B<=N),表示有一条单向铁路从城市A到城市B。
Output
对于每组数据,输出一行,表示最少的逃票次数。
若无论逃票多少次都无法到达,输出 -1.
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
int n,m;
long long k;
int cost[100010]; //记录每个站的票价
long long dist[100010]; //维护进第i 个站的最小费用
int ts[100010]; //维护第I个站前最少逃票次数
const long long INF=200000000000000; // INF>10的5 * 10 的8
vector<int>e[100010]; //记录边
void SPFA()
{
queue<int>que;
que.push(1);
dist[1]=cost[1];
ts[1]= (dist[1]<=k)?0:1;
vector<int>::iterator it;
while(que.size())
{
int cur=que.front();que.pop();
for(it=e[cur].begin();it!=e[cur].end();it++)
{
if(*it==n){
dist[n]=min(dist[cur],dist[n]); //这一步只是为了方便判断是否可以到达
ts[n]=min(ts[n],ts[cur]);
}
else{
long long val=dist[cur]+cost[*it]; //维护逃票次数最少基础上维护最小费用
int step= val<=k?0:ts[cur]+1;
if(ts[*it]>step){
ts[*it]=step;
dist[*it]=val;
que.push(*it);
}else if(ts[*it]==step&&dist[*it]>val){
dist[*it]=val;
que.push(*it);
}
}
}
}
}
int deal()
{
if(dist[n]==INF) return -1;
else return ts[n];
}
int main()
{
//freopen("in.in","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
cin>>k;
for(int i=1;i<=n;i++)
scanf("%d",&cost[i]);
for(int i=1;i<=n;i++) // void clear()
{
e[i].clear();
ts[i]=100010;
dist[i]=INF;
}
int a,b;
while(m--)
{
scanf("%d%d",&a,&b);
if(a!=b&&a!=n) e[a].push_back(b);
}
SPFA();
printf("%d\n",deal());
}
return 0;
}