poj 3268 双向dijkstra

来源:互联网 发布:java maven 打包成war 编辑:程序博客网 时间:2024/05/19 07:08

题目:

Silver Cow Party
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 19402 Accepted: 8864

Description

One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤ X ≤ N). A total of M (1 ≤ M ≤ 100,000) unidirectional (one-way roads connects pairs of farms; road i requires Ti (1 ≤ Ti ≤ 100) units of time to traverse.

Each cow must walk to the party and, when the party is over, return to her farm. Each cow is lazy and thus picks an optimal route with the shortest time. A cow's return route might be different from her original route to the party since roads are one-way.

Of all the cows, what is the longest amount of time a cow must spend walking to the party and back?

Input

Line 1: Three space-separated integers, respectively: NM, and X 
Lines 2..M+1: Line i+1 describes road i with three space-separated integers: AiBi, and Ti. The described road runs from farm Aito farm Bi, requiring Ti time units to traverse.

Output

Line 1: One integer: the maximum of time any one cow must walk.

Sample Input

4 8 21 2 41 3 21 4 72 1 12 3 53 1 23 4 44 2 3

Sample Output

10

Hint

Cow 4 proceeds directly to the party (3 units) and returns via farms 1 and 3 (7 units), for a total of 10 time units.

4个顶点,8条单向边,x=2,每个点走到x点再走回去有一个最短路,求所有点最短路中的最大值。

单向边,来回最短路可能不一样。


分析:

朴素的想法是可以对每个点跑一遍dijkstra,记录从i到x的最短路和从x到每个点的最短路(多源最短路,跑n遍);

分析得,回去的时候其实是从x出发的单源最短路。只有来的时候是多源问题,比较复杂,这时考虑到反向建图并将起点和终点也反过来,由于路径长度不变,这样可以将问题转换成从x出发跑一遍dijkstra,复杂度降低。


代码:

1.n遍dijkstra

#include <stdio.h>#include <iostream>#include <queue>#include <vector>#include <algorithm>#include <math.H>#include <limits.h>using namespace std;const int maxn=1009;const int inf=(INT_MAX)/3;typedef pair<int,int> p;struct edge{int to;int cost;edge(int to,int cost){//构造函数 this->to=to;this->cost=cost;}};int n,m,x,da[maxn],db[maxn],dt[maxn];vector<edge> g[maxn];void dijkstra(int s,int d[]){priority_queue<p,vector<p>,greater<p> >qu;//堆按照p的first(最短距离)排序,小在前 fill(d,d+maxn,inf);d[s]=0;qu.push(p(0,s));//从起点出发到顶点s的最短距离为0while(!qu.empty()){p temp=qu.top();qu.pop();if(temp.first>d[temp.second]) continue;//跳过更新过程中入队的非最小值 for(int i=0;i<g[temp.second].size();++i){//遍历该顶点连出的每条边 edge e=g[temp.second][i];if(d[e.to]>d[temp.second]+e.cost){d[e.to]=d[temp.second]+e.cost;qu.push(p(d[e.to],e.to));}}}}int main(){//772k 532msint a,b,c;while(~scanf("%d%d%d",&n,&m,&x)){for(int i=1;i<=m;++i){scanf("%d%d%d",&a,&b,&c);g[a].push_back(edge(b,c));}for(int i=1;i<=n;++i){if(i==x){dijkstra(x,db);}dijkstra(i,dt);da[i]=dt[x];}int ans=0;for(int i=1;i<=n;++i){ans=max(ans,da[i]+db[i]);}printf("%d\n",ans);}return 0;}



2.两遍dijkstra

#include <stdio.h>#include <iostream>#include <queue>#include <vector>#include <algorithm>#include <math.H>#include <limits.h>using namespace std;const int maxn=1009;const int inf=(INT_MAX)/3;typedef pair<int,int> p;struct edge{int to;int cost;edge(int to,int cost){//构造函数 this->to=to;this->cost=cost;}};int n,m,x,da[maxn],db[maxn];vector<edge> g1[maxn],g2[maxn];void dijkstra(int s,int d[],vector <edge> g[]){priority_queue<p,vector<p>,greater<p> >qu;//堆按照p的first(最短距离)排序,小在前 fill(d,d+maxn,inf);d[s]=0;qu.push(p(0,s));//从起点出发到顶点s的最短距离为0while(!qu.empty()){p temp=qu.top();qu.pop();if(temp.first>d[temp.second]) continue;//跳过更新过程中入队的非最小值 for(int i=0;i<g[temp.second].size();++i){//遍历该顶点连出的每条边 edge e=g[temp.second][i];if(d[e.to]>d[temp.second]+e.cost){d[e.to]=d[temp.second]+e.cost;qu.push(p(d[e.to],e.to));}}}}int main(){//880k 47msint a,b,c;while(~scanf("%d%d%d",&n,&m,&x)){for(int i=1;i<=m;++i){scanf("%d%d%d",&a,&b,&c);g1[a].push_back(edge(b,c));g2[b].push_back(edge(a,c));}dijkstra(x,da,g1);dijkstra(x,db,g2);int ans=0;for(int i=1;i<=n;++i){ans=max(ans,da[i]+db[i]);}printf("%d\n",ans);}return 0;}





0 0
原创粉丝点击