文章标题 POJ 3268 : Silver Cow Party (最短路--spfa)

Silver Cow Party

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
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.
题意: 有n块田地,从1~n,然后会在x这块田地上举行一个派对,然后有m条单向边,从a地指向b地,第i条路需要花费Ti的时间。现在每个田地上有一头牛,然后这些牛想尽可能用短的时间去到x这个田地,然后用尽可能短的时间回家。现在要求出这些牛去派对然后回家总共的时间中最长的输出来。
分析:先用一个数组来存储每只牛所用的时间,然后先求每只牛从他的田地去聚会的田地的时间,这些时间可以用最短路来求,而我用的是spfa,然后再求一次聚会的田地到其他田地的最短路,求出回家的所用的最短时间,最后在这所用的时间中求出用时最短的。即是答案。

代码:

#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<vector>
#include<math.h>
#include<map>
#include<queue> 
#include<algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
int n,m,x;
struct Edge{//边的结构体 
    int v;//边终点 
    int t;//时间 
    Edge(int v_,int t_){
        v=v_;
        t=t_;
    }
    Edge(){}
};
vector <Edge> G[1005];//用来存储图的邻接表 
int dis[1005];//求最短路时用来求到各个点的最短距离 
int vis[1005];
int ans[1005];//存储答案的 
int spfa(int s){
    queue<int>q;
    memset(vis,0,sizeof (vis)); 
    for (int i=0;i<1005;i++) dis[i]=inf;
    dis[s]=0;
    vis[s]=1;
    q.push(s);
    while (!q.empty()){
        int u=q.front();q.pop();vis[u]=0;
        for (int i=0;i<G[u].size();i++){
            int v=G[u][i].v;
            int t=G[u][i].t;
            if (dis[v]>dis[u]+t){//松弛 
                dis[v]=dis[u]+t;
                if (!vis[v]){
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
    ans[s]+=dis[x];//到达聚会的点的距离加起来 
}
int main ()
{
    int a,b,t;
    while (cin>>n>>m>>x){
        for (int i=0;i<1005;i++) G[i].clear();
        memset (dis,0,sizeof (dis));
        memset (ans,0,sizeof (ans));
        for (int i=0;i<m;i++){
            cin>>a>>b>>t;
            G[a].push_back(Edge(b,t));
        }
        for (int i=1;i<=n;i++){
            if (i==x)continue;
            spfa(i);
        }
        spfa(x);//再求回家的最短路 
        for (int i=1;i<=n;i++){
            ans[i]+=dis[i];//加起来 
        }
        int maxn=ans[1];
        for (int i=2;i<=n;i++){
            maxn=max(maxn,ans[i]);//将最大值求出来 
        }
        cout<<maxn<<endl;//答案 
    }   
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值