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. .Net core使用Quartz.Net 实现定时任务

    很多情况下,我们需要完成一些定时执行的功能,用很多定时工具,像:hangfire,TimeJob,以及Quartz.net,不过quartz.net 比较精确一些,功能也比较强大,所以我选择了Quar ...

  2. 使用WIn10自带的Linux子系统

    最近一直有安装虚拟机的想法,今天刚刚知道win10有自带的Linux子系统,就准备试一下: 首先要保证自己的电脑处于开发者选项: 然后就要在控制面板的程序和功能页面点击“启用或者关闭WIndows功能 ...

  3. python 两个面试题

    1.下面程序的运算结果是什么?? class Parent: def func(self): print("In Parent func") def __init__(self): ...

  4. 从零开始一个http服务器(二)-请求request解析

    从零开始一个http服务器 (二) 代码地址 : https://github.com/flamedancer/cserver git checkout step2 解析http request 观察 ...

  5. SpaceVim 语言模块 lua

    原文连接: https://spacevim.org/cn/layers/lang/lua/ 模块简介 启用模块 快捷键 交互式编程 运行当前脚本 模块简介 这一模块为在 SpaceVim 中进行 l ...

  6. TensorFlow之tf.nn.dropout():防止模型训练过程中的过拟合问题

    一:适用范围: tf.nn.dropout是TensorFlow里面为了防止或减轻过拟合而使用的函数,它一般用在全连接层 二:原理: dropout就是在不同的训练过程中随机扔掉一部分神经元.也就是让 ...

  7. 如何写chrome扩展

    转载:http://www.cnblogs.com/pingfan1990/p/4560215.html 最近看到公司同事经常写chrome扩展,来提高生成效率,回想想自己以前也写过chrome扩展, ...

  8. WPF的退出

    很多时候,会自己写退出程序的代码. 比如,先显示登录框(LogIn),成功后隐藏它,并显示一个主窗体(MainWin),或者外部还调用了其他App,当你关闭MainWin不一定会直接退出整个程序的. ...

  9. 北京Uber优步司机奖励政策(1月28日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  10. 苏州Uber人民优步奖励政策

    人民优步(People's Uber)资费标准 起步价(Base Fare):¥0.00 每公里(Per KM):¥1.65 每分钟(Per Min):¥0.30 最低价(Min Fare):¥9.0 ...