您的位置:首页 > 其它

POJ 3268 Silver Cow Party(双向最短路)

2016-08-26 13:49 423 查看
Silver Cow Party

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: N, M, and X 

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 Ai to 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 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

题目大意:有N头牛来自N个农场,它们要去编号为X农场参加一个大型的聚会。所有的牛都比较懒,它们只选择到达目的地最近的路。参加完聚会之后,每头牛都要走回自己的农场。由于道路是单向的,所以回去的路可能和来参加派对的路程不同。现在给出所有农场的编号和农场之间的道路情况,求所有的牛中走的路最长的路径长度。
解题思路1:由于是求1到N与X之间的最短路。所以想到用Floyd算法,但是这道题数据量比较大,用Floyd会超时,所以可以将Dijkstra算法改动一下,使它可以求出任意两点间的最短路。开二维数组保存最短距离即可。

代码如下:

#include <cstdio>
#include <queue>
#include <cstring>
#include <climits>
#define INF INT_MAX / 10
using namespace std;
typedef pair<int,int> P;
const int maxn = 1005;
const int maxm = 100005;
int first[maxn],d[maxn][maxn],e;
int next[maxm],v[maxm],w[maxm];
int n,m,x;
void init()
{
memset(first,-1,sizeof(first));
e = 1;
}
void add_edge(int from,int to,int dis)
{
v[e] = to;
next[e] = first[from];
w[e] = dis;
first[from] = e++;
}
priority_queue<P,vector<P>,greater<P> > que;
void dijkstra(int s)
{
while(que.size()) que.pop();
for(int i = 1;i <= n;i++) d[s][i] = INF;
d[s][s] = 0;
que.push(P(0,s));
while(que.size()){
P p = que.top();
que.pop();
int u = p.second;
if(d[s][u] < p.first) continue;
for(int i = first[u];i != -1;i = next[i]){
if(d[s][v[i]] > d[s][u] + w[i]){
d[s][v[i]] = d[s][u] + w[i];
que.push(P(d[s][v[i]],v[i]));
}
}
}
return ;
}

int main()
{
int a,b,c;
while(scanf("%d %d %d",&n,&m,&x) != EOF){
init();
for(int i = 0;i < m;i++){
scanf("%d %d %d",&a,&b,&c);
add_edge(a,b,c);
}
int ans = 0;
for(int i = 1;i <= n;i++){
dijkstra(i);
}
for(int i = 1;i <= n;i++){
ans = max(ans,d[i][x] + d[x][i]);
}
printf("%d\n",ans);
}
return 0;
}
解题思路2:上面的代码在POJ上跑了400+MS,比较慢。仔细思考一下发现还可以再优化。我们只需要求以X为起点和终点的最短路,并不需要求其他两点之间的最短路。所以我们可以建两个图,一个正向图一个反向图,然后在两个图上各跑一次Dijkstra(X)就可以了。在正向图上求的是回家的最短距离,在反向图上求的是到X的距离,然后两个距离相加取最大值即可。这样优化过后在POJ上可以跑47MS,算的上比较快的了。

代码如下:

#include <cstdio>
#include <queue>
#include <cstring>
#include <climits>
#include <algorithm>
#define INF INT_MAX / 10
using namespace std;
typedef pair<int,int> P;
const int maxn = 1005;
const int maxm = 100005;
int first[maxn],d[maxn],dd[maxn],e;
int next[maxm],v[maxm],w[maxm];
int a[maxm],b[maxm],c[maxm];
int n,m,x;
void init()
{
memset(first,-1,sizeof(first));
e = 1;
}
void add_edge(int from,int to,int dis)
{
v[e] = to;
next[e] = first[from];
w[e] = dis;
first[from] = e++;
}
priority_queue<P,vector<P>,greater<P> > que;
void dijkstra(int s)
{
while(que.size()) que.pop();
for(int i = 1;i <= n;i++) d[i] = INF;
d[s] = 0;
que.push(P(0,s));
while(que.size()){
P p = que.top();
que.pop();
int u = p.second;
if(d[u] < p.first) continue;
for(int i = first[u];i != -1;i = next[i]){
if(d[v[i]] > d[u] + w[i]){
d[v[i]] = d[u] + w[i];
que.push(P(d[v[i]],v[i]));
}
}
}
}

int main()
{
while(scanf("%d %d %d",&n,&m,&x) != EOF){
for(int i = 0;i < m;i++){
scanf("%d %d %d",&a[i],&b[i],&c[i]);
}
int ans = 0;
init();
for(int i = 0;i < m;i++)
add_edge(a[i],b[i],c[i]);
dijkstra(x);
memcpy(dd+1,d+1,sizeof(d));
init();
for(int i = 0;i < m;i++)
add_edge(b[i],a[i],c[i]);
dijkstra(x);
for(int i = 1;i <= n;i++){
d[i] += dd[i];
}
for(int i = 1;i <= n;i++)
ans = max(ans,d[i]);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  POJ