给定n个点,m条有向边,邮箱容量c。
起点在1,终点在n,开始邮箱满油。
下面m行表示起点终点和这条边的耗油量(就是长度)
再下面给出一个数字m表示有P个加油站,可以免费加满油。
下面一行P个数字表示加油站的点标。
再下面一个整数Q
下面Q行 u v 表示在u点有销售站,可以卖掉邮箱里的任意数量的油,每以单位v元。
问跑到终点能获得最多多少元。
再华丽的描述外表也掩盖不住水题的性质。
这个题的下手点在 : 卖油只能卖1次,假设在i点处卖油 , 那么我应该要知道2个量,一个是现在油箱里还有多少油,一个是到达终点
还需要多少油。差值就可以卖了。
最大值 1 ,枚举 2 , 满足i处油箱有最多 ; i到n耗油最少。 那么:
正向边 : 求个每个点的最大剩余油量 dist1[i],
反向边 : 求每个点距离终点的最少还需的油量 dist2[i]。
然后枚举一下每个销售点即可,( dist1[i] - dist2[i] ) * wi 。
const int maxn = 1008 ;
const int maxm = 100008 ;
const int inf = 2000000000 ;
struct Graph{
int lis[maxn] ;
int id ;
struct Edge{
int v ;
int w ;
int next ;
}e[maxm];
void Clear(){
memset(lis , -1 , sizeof(lis)) ;
id = 0 ;
}
void add(int u, int v , int w){
e[id].v = v ;
e[id].w = w ;
e[id].next = lis[u] ;
lis[u] = id++ ;
}
};
Graph g1 , g2 ;
int n , m , c ;
bool fuel[maxn] ;
int sell[maxn][2] ;
bool in[maxn] ;
int dist1[maxn] , dist2[maxn] ;
void spfa1(int s){
queue<int> q ;
memset(in , 0 , sizeof(in)) ;
in[s] = 1 ;
q.push(s) ;
fill(dist1+1 , dist1+1+n , -inf) ;
dist1[s] = c ;
while(! q.empty()){
int u = q.front() ; q.pop() ;
in[u] = 0 ;
for(int i = g1.lis[u] ; i != -1 ; i = g1.e[i].next){
int v = g1.e[i].v , w = g1.e[i].w ;
if(dist1[u] >= w){ //能走完这条路
int t = dist1[u] - w ;
if(fuel[v]) t = c ;
if(dist1[v] < t){
dist1[v] = t ;
if(! in[v]){
in[v] = 1 ; q.push(v) ;
}
}
}
}
}
}
void spfa2(int s){
queue<int> q ;
memset(in , 0 , sizeof(in)) ;
in[s] = 1 ;
q.push(s) ;
fill(dist2+1 , dist2+1+n , inf) ;
dist2[s] = 0 ;
while(! q.empty()){
int u = q.front() ; q.pop() ;
in[u] = 0 ;
for(int i = g2.lis[u] ; i != -1 ; i = g2.e[i].next){
int v = g2.e[i].v , w = g2.e[i].w ;
if(dist2[u] + w <= c){ //能走完这条路
int t = dist2[u] + w ;
if(fuel[v]) t = 0 ;
if(dist2[v] > t){
dist2[v] = t ;
if(! in[v]){
in[v] = 1 ; q.push(v) ;
}
}
}
}
}
}
int main(){
int i , u , v , w , p , q , s ;
while(cin>>n>>m>>c){
g1.Clear() , g2.Clear() ;
for(i = 1 ; i <= m ; i++){
scanf("%d%d%d" , &u , &v , &w) ;
g1.add(u , v , w) ;
g2.add(v , u , w) ;
}
memset(fuel , 0 , sizeof(fuel)) ;
scanf("%d" ,&p) ;
for(i = 1 ; i <= p ; i++){
scanf("%d" ,&u) ;
fuel[u] = 1 ;
}
scanf("%d" , &q) ;
for(i = 1 ; i <= q ; i++)
scanf("%d%d" ,&sell[i][0] , &sell[i][1]) ;
spfa1(1) ;
if(dist1[n] < 0){
puts("-1") ; continue ;
}
spfa2(n) ;
s = 0 ;
for(i = 1 ; i <= q ; i++){
u = sell[i][0] , w = sell[i][1] ;
if(dist1[u] >= dist2[u])
s = max(s , (dist1[u] - dist2[u]) * w ) ;
}
printf("%d\n" , s) ;
}
return 0 ;
}