题目:
Time Limit: 2000MS | Memory Limit: 65536K | |
Total 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
Lines 2.. M+1: Line i+1 describes road i with three space-separated integers: Ai, Bi, and Ti. The described road runs from farm Aito farm Bi, requiring Ti time units to traverse.
Output
Sample Input
4 8 2 1 2 4 1 3 2 1 4 7 2 1 1 2 3 5 3 1 2 3 4 4 4 2 3
Sample Output
10
Hint
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的最短距离为0
while(!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 532ms
int 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的最短距离为0
while(!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 47ms
int 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;
}