Silver Cow Party (Dijkstra)

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 ≤ XN). 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个牛场的N头牛要去X牛场开party,完事之后再各回各家,牛们都比较懒,

因此来回都走最短路线(同一条路来回用时不一定相同),要求妹头牛来回所花时间最大值

思路:

此题为最短路问题,但问题是

去的时候是多源到单源的最短路问题(所有牛从家去X牛场)---------》寸边关系时反向存放,转化为单源到多源的最短路问题-----》Dijkstra算法

回来时候是单源到多源的最短路问题(所有牛从X牛场回各家)-------》常规Dijkstra算法

AC代码:

#include<stdio.h>
#include<string.h>
#define MAX 1005
#define Inf 0x3f3f3f3f
using namespace std;
int e1[MAX][MAX],e2[MAX][MAX];   //e1记录所有牛去的路线图的反方向 e2记录回的时候的方向(即已知方向)
int dis1[MAX],dis2[MAX];  //dis1记录去时所花的时间 dis2记录回时所花时间
int n,m,x;
void Dijkstra(int k,int dis[] );
int main(){
    scanf("%d%d%d",&n,&m,&x);
    memset(e1,Inf,sizeof(e1));  //memset 可以把数组初始化为0,-1,0x3f3f3f3f(为无限大)
    memset(e2,Inf,sizeof(e2));
    int i;
    for(i=1;i<=n;i++)
        e2[i][i]=e1[i][i]=0;
    while(m--){
        int a,b,t;
        scanf("%d%d%d",&a,&b,&t);  //去的时候反向存
        if(t<e1[b][a]) e1[b][a]=t; 
        if(t<e2[a][b]) e2[a][b]=t;
    }
    Dijkstra(1,dis1);
    Dijkstra(2,dis2);
    int max=0;
    for(i=1;i<=n;i++){
        int s=dis1[i]+dis2[i];  //来回时间花最多的
        max=max>s?max:s;
    }
    printf("%d\n",max);
return 0;
}
void Dijkstra(int k,int dis[] ){ //当k为1时是去时代最短路径问题,k为2时是回时的最短路径问题
     int i,j;
     for(i=1;i<=n;i++)
        if(k==1) dis[i]=e1[x][i];
        else dis[i]=e2[x][i];
     int book[MAX];
     memset(book,0,sizeof(book));
     book[x]=1;

     for(i=1;i<=n;i++){   //Dijkstra算法的核心操作
        int min=Inf;
        int u;
        for(j=1;j<=n;j++){
            if(!book[j]&&dis[j]<min){
                min=dis[j];
                u=j;
            }
        }
        book[u]=1;
        if(k==1)            //松弛操作
        for(j=1;j<=n;j++){
            if(e1[u][j]<Inf){
                if(dis[j]>dis[u]+e1[u][j]){
                    dis[j]=dis[u]+e1[u][j];
                }
            }
        }
        else
                for(j=1;j<=n;j++){
            if(e2[u][j]<Inf){
                if(dis[j]>dis[u]+e2[u][j]){
                    dis[j]=dis[u]+e2[u][j];
                }
            }
        }

     }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值