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. 关于linux‘RedHat6.9在VMware虚拟机中的安装步骤

    redhat支持多种安装方式:光盘安装,硬盘安装和网络安装等,可以根据个人的实际情况来选择.我在这里选择的是光盘安装的方式安装RHEL6.9.(以下简称6.9) 1.首先准备好6.9的光盘镜像,在安装 ...

  2. Java实现“睡排序”——线程池Executors的使用

    前提 之前在知乎上看见一个有意思的排序算法——睡排序. 睡排序最早好像是4chan上一个用户用shell脚本实现的: 算法思想简洁明了:利用进程的sleep来实现 越大的数字越迟输出. 虽然像2L说的 ...

  3. HTML表格-table

    表格 表格由 <table> 标签来定义. 每个表格均有若干行(由 <tr> 标签定义),每行被分割为若干单元格(由 <td> 标签定义). 字母 td 指表格数据 ...

  4. 干货分享:QQ群排名霸屏优化规则靠前的新技术

    谈起QQ群排名的优化规则,很多人又爱又恨,原因很简单,爱他的都是引流效果是非常好的,通过关键词搜索排名好的技术,能排到全国默认前三,叫人怎能不爱他,恨的原因也恨简单,无论你的群完善的再怎么好,好像都无 ...

  5. 18CCPC网赛A 贪心

    Buy and Resell Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  6. java-执行流程控制语句

    就像有知觉的生物一样,程序必须在执行的过程中控制它的世界,并做出选择.java使用执行流程控制语句做出选择. 1.选择语句 if if(布尔表达式){ 业务逻辑1; }else{ 业务逻辑2: } s ...

  7. 关于条件约束问题的无偏差统计——一个偏差控制型生成器(Unbiased Statistics of a Constraint Satisfaction Problem – a Controlled-Bias Generator——by Denis Berthier)

    论文地址:https://hal.archives-ouvertes.fr/hal-00641955 Unbiased Statistics of a Constraint Satisfaction ...

  8. psd 转换 html

    http://www.docin.com/search.do?searchcat=2&nkey=psd+to+html

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

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

  10. 天津Uber优步司机奖励政策(12月28日到12月29日)

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