Petya loves volleyball very much. One day he was running late for a volleyball match. Petya hasn't bought his own car yet, that's why he had to take a taxi. The city has n junctions, some of which are connected by two-way roads. The length of each road is defined by some positive integer number of meters; the roads can have different lengths.

Initially each junction has exactly one taxi standing there. The taxi driver from the i-th junction agrees to drive Petya (perhaps through several intermediate junctions) to some other junction if the travel distance is not more than ti meters. Also, the cost of the ride doesn't depend on the distance and is equal to ci bourles. Taxis can't stop in the middle of a road. Each taxi can be used no more than once. Petya can catch taxi only in the junction, where it stands initially.

At the moment Petya is located on the junction x and the volleyball stadium is on the junction y. Determine the minimum amount of money Petya will need to drive to the stadium.

Input

The first line contains two integers n and m (1 ≤ n ≤ 1000, 0 ≤ m ≤ 1000). They are the number of junctions and roads in the city correspondingly. The junctions are numbered from 1 to n, inclusive. The next line contains two integers x and y (1 ≤ x, y ≤ n). They are the numbers of the initial and final junctions correspondingly. Next m lines contain the roads' description. Each road is described by a group of three integers uiviwi (1 ≤ ui, vi ≤ n, 1 ≤ wi ≤ 109) — they are the numbers of the junctions connected by the road and the length of the road, correspondingly. The next n lines contain n pairs of integers ti and ci (1 ≤ ti, ci ≤ 109), which describe the taxi driver that waits at the i-th junction — the maximum distance he can drive and the drive's cost. The road can't connect the junction with itself, but between a pair of junctions there can be more than one road. All consecutive numbers in each line are separated by exactly one space character.

Output

If taxis can't drive Petya to the destination point, print "-1" (without the quotes). Otherwise, print the drive's minimum cost.

Please do not use the %lld specificator to read or write 64-bit integers in С++. It is preferred to use cin, cout streams or the %I64d specificator.

题目大意:给n个点,m条双向边,每条路均有一个距离,从一个点x出发,最多能花费c[x]走距离t[x]的路,求从起点到终点的最小花费。

官方题解1:

Some of the things which I did not take note of during the competition which prevented my solution from passing. Use adjacency list instead of matrix as the number of roads are only 1000. The question says that there can be multiple roads between junctions so updation needs to be done to adj[s][e] when a lower distance comes up.
 
Approach
 
A combination of djikstra and DFS allows us to find the minimum cost incurred in traversing the points. Update your djikstra cost array at all nodes which can be visited from the taxi you are in. This can be done using DFS. Again find the minimum cost junction and continue. If at the end you are not able to reach the destination output should be -1.
官方题解2:
At first in this simple problem you need to find shortest path between all pair of junctions. That can’t be done using O(N^3) algorithms, so you must use Dijkstra algorithm to find this in O(N*N*logN) time. Next part of this problem is to create new matrix, G[i][j] = C[i], if D[i][j] <= R[i], else G[i][j] = INF. Here D[i][j] – length of shortest path between I and j. So, result is shortest path between X and Y using matrix G. That can be done using simple Dijkstra algorithm.
思路:
这题看完题目就会做了,得益于之前做过某题:http://www.cnblogs.com/oyking/archive/2013/06/04/3116617.html,大题思路为,暴搜每个点走距离t[x]能到达的点,为每对这样的点之间连一条边,权值为c[x],然后在后来得到的图上直接求最短路径(最普通的SPFA算法)即可。
另,一开始若暴搜没有剪枝,我曾试过把最短路径图上的边都输出来,发现一个小图却会有很多边,果断优化。之后想挫了以为搜索的时候每个点经过一次就可以了,后来发现这样不对,因为有可能第一次经过点y的时候,还可以走距离A,第二次经过点y的时候,还可以做距离B,完全有可能是A<B。基于这个想法,类似可以把A记录下来,若A<B才继续搜索,否则剪枝。
不剪枝的话生成的边太多了,会爆(AC之后手贱交了一次,因为眼挫以为自己WA了)
PS:这代码AC过一次之后就没AC过了,这是什么现象我至今没搞懂……
 
 #include <cstdio>
#include <cstring>
#include <queue>
using namespace std; typedef long long LL; const int MAXN = ;
const int MAXM = ;
int n, m, x, y; void tle() {
while() ;
} struct Shortest_path {
int head[MAXN], inque[MAXN];
int next[MAXM], to[MAXM], cost[MAXM];
int ecnt, st, ed;
LL dis[MAXN]; void SPFA() {
queue<int> Q;
Q.push(st);
memset(inque, , sizeof(inque));
memset(dis, , sizeof(dis));
dis[st] = ;
while(!Q.empty()) {
int u = Q.front(); Q.pop();
inque[u] = false;
for(int p = head[u]; p; p = next[p]) {
int v = to[p];
if(dis[v] < || dis[v] > dis[u] + cost[p]) {
dis[v] = dis[u] + cost[p];
//printf("%d %I64d\n",v,dis[v]);
if(!inque[v]) {
inque[v] = true;
Q.push(v);
}
}
}
}
} void addEdge(int u, int v, int c) {
to[ecnt] = v; cost[ecnt] = c;
next[ecnt] = head[u]; head[u] = ecnt++;
//printf("%d->%d %d\n",u,v,c);
//if(ecnt == MAXM) tle();
} void init(int ss, int tt) {
st = ss; ed = tt;
ecnt = ;
memset(head, , sizeof(head));
} LL solve() {
SPFA();
return dis[ed];
}
} G; const int M = MAXN * ; struct Tree {
int head[MAXN], c[MAXN], t[MAXN];
int small[MAXN];
int next[M], to[M], cost[M];
int ecnt; void dfs(int root, int u, int rest) {
for(int p = head[u]; p; p = next[p]) {
int v = to[p];
if(rest - cost[p] < small[v]) continue;
if(rest - cost[p] >= ) {
G.addEdge(root, v, c[root]);
small[v] = rest - cost[p];
if(rest) dfs(root, v, rest - cost[p]);
}
}
} void addEdge(int u, int v, int cc) {
to[ecnt] = v; cost[ecnt] = cc;
next[ecnt] = head[u]; head[u] = ecnt++;
//printf("%d->%d %d\n",u,v,cc);
} void init() {
ecnt = ;
memset(head, , sizeof(head));
} void make_G() {
for(int i = ; i <= n; ++i) {
memset(small, , sizeof(small));
small[i] = 0x7fffffff;
dfs(i, i, t[i]);
}
}
} T; int main() {
while(scanf("%d%d", &n, &m) != EOF) {
scanf("%d%d", &x, &y);
G.init(x, y);
T.init();
int u, v, c;
for(int i = ; i < m; ++i) {
scanf("%d%d", &u, &v);
scanf("%d", &c);
T.addEdge(u, v, c);
T.addEdge(v, u, c);
}
for(int i = ; i <= n; ++i) {
scanf("%d", &T.t[i]);
scanf("%d", &T.c[i]);
}
T.make_G();
printf("%I64d\n", G.solve());
}
}

献上真·AC代码,这个应该没问题了,理论上来说上面的那个代码可以卡(可以卡边数卡爆),实际上可以直接用SPFA求第一张图的最短路然后再判断某点x是否能到底某点y,SPFA在稀疏图上常数灰常小,在这提上是灰常适用的。

PS:下面的两个类实际上可以合在一起,但是我懒得搞了就这样吧……

 #include <cstdio>
#include <cstring>
#include <queue>
using namespace std; typedef long long LL; const int MAXN = ;
const int MAXM = ;
int n, m, x, y; void tle() {
while() ;
} struct Shortest_path {
int head[MAXN], inque[MAXN];
int next[MAXM], to[MAXM], cost[MAXM];
int ecnt, st, ed;
LL dis[MAXN]; void SPFA() {
queue<int> Q;
Q.push(st);
memset(inque, , sizeof(inque));
memset(dis, , sizeof(dis));
dis[st] = ;
while(!Q.empty()) {
int u = Q.front(); Q.pop();
inque[u] = false;
for(int p = head[u]; p; p = next[p]) {
int v = to[p];
if(dis[v] < || dis[v] > dis[u] + cost[p]) {
dis[v] = dis[u] + cost[p];
//printf("%d %I64d\n",v,dis[v]);
if(!inque[v]) {
inque[v] = true;
Q.push(v);
}
}
}
}
} void addEdge(int u, int v, int c) {
to[ecnt] = v; cost[ecnt] = c;
next[ecnt] = head[u]; head[u] = ecnt++;
//printf("%d->%d %d\n",u,v,c);
//if(ecnt == MAXM) tle();
} void init(int ss, int tt) {
st = ss; ed = tt;
ecnt = ;
memset(head, , sizeof(head));
} LL solve() {
SPFA();
return dis[ed];
}
} G; const int M = MAXN * ; struct Tree {
int head[MAXN], inque[MAXN], c[MAXN], t[MAXN];
int next[M], to[M], cost[M];
int ecnt;
LL dis[MAXN]; void SPFA(int st) {
queue<int> Q;
Q.push(st);
memset(inque, , sizeof(inque));
memset(dis, , sizeof(dis));
dis[st] = ;
while(!Q.empty()) {
int u = Q.front(); Q.pop();
inque[u] = false;
for(int p = head[u]; p; p = next[p]) {
int v = to[p];
if(dis[v] < || dis[v] > dis[u] + cost[p]) {
dis[v] = dis[u] + cost[p];
//printf("%d %I64d\n",v,dis[v]);
if(!inque[v]) {
inque[v] = true;
Q.push(v);
}
}
}
}
} void addEdge(int u, int v, int cc) {
to[ecnt] = v; cost[ecnt] = cc;
next[ecnt] = head[u]; head[u] = ecnt++;
//printf("%d->%d %d\n",u,v,cc);
} void init() {
ecnt = ;
memset(head, , sizeof(head));
} void make_G() {
for(int i = ; i <= n; ++i) {
SPFA(i);
for(int j = ; j <= n; ++j) {
if(i == j) continue;
if(dis[j] >= && dis[j] <= t[i]) {
G.addEdge(i, j, c[i]);
}
}
}
}
} T; int main() {
int i;
while(scanf("%d%d", &n, &m) != EOF) {
scanf("%d%d", &x, &y);
G.init(x, y);
T.init();
int u, v, c;
for(i = ; i < m; ++i) {
scanf("%d%d", &u, &v);
scanf("%d", &c);
T.addEdge(u, v, c);
T.addEdge(v, u, c);
}
for(i = ; i <= n; ++i) {
scanf("%d", &T.t[i]);
scanf("%d", &T.c[i]);
}
T.make_G();
printf("%I64d\n", G.solve());
}
}

Codeforces 96D Volleyball(最短路径)的更多相关文章

  1. Codeforces 95C Volleyball(最短路)

    题目链接:http://codeforces.com/problemset/problem/95/C C. Volleyball time limit per test 2 seconds memor ...

  2. CF - 96D - Volleyball

    题意:一个无向图,有n个点,m条边,每条边有距离w,每个点有两个属性(1.从这点出发能到的最远距离,2.从这点出发的费用(不论走多远都一样)),一个人要从点x到点y,问最小费用是多少. 题目链接:ht ...

  3. Codeforces Beta Round #77 (Div. 1 Only) C. Volleyball (最短路)

    题目链接:http://codeforces.com/contest/95/problem/C 思路:首先dijkstra预处理出每个顶点到其他顶点的最短距离,然后如果该出租车到某个顶点的距离小于等于 ...

  4. 【codeforces 95C】Volleyball

    [题目链接]:http://codeforces.com/problemset/problem/95/C [题意] 给你n个点,m条边; 每个点有一辆出租车; 可以到达离这个点距离不超过u的点,且在这 ...

  5. Codeforces 601A:The Two Routes 宽搜最短路径

    A. The Two Routes time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...

  6. Codeforces Round #368 (Div. 2)

    直达–>Codeforces Round #368 (Div. 2) A Brain’s Photos 给你一个NxM的矩阵,一个字母代表一种颜色,如果有”C”,”M”,”Y”三种中任意一种就输 ...

  7. Codeforces Training S03E01泛做

    http://codeforces.com/gym/101078 和ysy.方老师一起打的virtual 打的不是很好...下面按过题顺序放一下过的题的题(dai)解(ma). A 给两个1~n的排列 ...

  8. Codeforces Round #130 (Div. 2) C. Police Station

    题目链接:http://codeforces.com/contest/208/problem/C 思路:题目要求的是经过1~N的最短路上的某个点的路径数 /  最短路的条数的最大值.一开始我是用spf ...

  9. Codeforces Round #103 (Div. 2) D. Missile Silos(spfa + 枚举边)

    题目链接:http://codeforces.com/problemset/problem/144/D 思路:首先spfa求出中心点S到其余每个顶点的距离,统计各顶点到中心点的距离为L的点,然后就是要 ...

随机推荐

  1. mybatis传单个参数,和<if>标签同时使用的问题

    // Mapper.java EmerEvent selectByAlarmId(Integer alarmId); // Mapper.xml <select id="selectB ...

  2. hdu_5187_zhx's contest

    Problem Description As one of the most powerful brushes, zhx is required to give his juniors n probl ...

  3. 10.31课程.this指向

    作用域: 浏览器给js的生存环境(栈). 作用域链: js中的关键字例如var.function...都可以提前声明,然后js由上到下逐级执行,有就使用,没有就在它的父级元素中查找.这就叫做作用域链. ...

  4. webuploader的一个页面多个上传按钮实例

    借鉴一位大佬的demo  附上他的github地址https://github.com/lishuqi 我把他的cxuploader.js改了不需要预览  直接上传图片后拿到回传地址给img标签显示图 ...

  5. Java代码注释

    单行注释: 选中代码,按下ctrl+/ 一条代码单行注释:选中一条代码按下ctrl+/,则为一条代码单行注释: 多条代码单行注释:选中多条代码按下ctrl+/,则为多条代码单行注释: 取消注释:对已经 ...

  6. 『Python基础-7』for循环 & while循环

    『Python基础-7』for循环 & while循环 目录: 循环语句 for循环 while循环 循环的控制语句: break,continue,pass for...else 和 whi ...

  7. ubuntu 防止软件包自动更新

    阻止软件包升级 有两种方法阻止软件包升级,使用dpkg,或者在Woody中使用APT. 使用dpkg,首先导出软件包选择列表: dpkg --get-selections \* > select ...

  8. c. 求阶乘和的方法(N的值不能太大)初学者

    #include <stdio.h> int main() { int n,i; int a=1;   //a设置为一个数的阶乘 int b;    //  b 设置为阶乘的和 for(i ...

  9. vue跨域访问

    第一次创建vue项目,画完静态页面一切顺利,准备和后台进行联调,问题来了,无论怎么调试使用Axios,jQuary还是使用原生的Ajax请求都访问不通(前提条件,另外一个人的电脑当成服务器,进行访问) ...

  10. R tutorial

    http://www.clemson.edu/economics/faculty/wilson/R-tutorial/Introduction.html https://www.youtube.com ...