poj 3268 Sliver cow Party 题解

本文介绍了一种使用双向Dijkstra算法求解两点间往返最短路径的方法,并通过实例代码详细展示了如何实现该算法。具体步骤包括:首先从一个点出发计算到其他所有点的最短距离并记录,然后反转边的方向重新计算,最后找出所有点中往返距离之和的最大值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

把终点当成起点求到达每一个点的最短路径。用两次Dijkstra求分别求来回的最短路径,第一次求完之后保存到tem数组,然后把去来的路径反过来再次求最短路径,最后求加和之后的最大值就是答案;

#include<iostream>
#include<stdio.h>
#include<cmath>
#include<cstring>
#include<stack>
#include<algorithm>
#include<queue>
#include<map>
#include<climits>
#define ll long long

using namespace std;
const int inf = 999999;
const int vex = 1005;

int v[vex][vex];
int dist[vex];
int vis[vex];
int tem[vex];

int n,m,x;

void dijkstra(int s){
    fill(dist + 1, dist + 1 + n, inf);
    fill(vis + 1, vis + 1 + n, 0);
    dist[s] = 0;
    for(int i = 1; i <= n; i++){
        int now = s;
        int temp = inf;
        for(int j = 1; j <= n; j++){
            if(!vis[j] && temp > dist[j]){
                temp = dist[j];
                now = j;
            }
        }
        vis[now] = 1;
        for(int j = 1; j <= n; j++){
            if(!vis[j] && dist[j] > dist[now] + v[now][j]){
                dist[j] = dist[now] + v[now][j];
            }
        }
    }
    if(tem[1] == -1){
        for(int i = 1; i <= n; i++){
            tem[i] = dist[i];
        }
    }

}

int main(){
    scanf("%d %d %d",&n,&m,&x);
//    for(int i = 1; i <= m; i++)
//        fill(v[i] + 1, v[i] + 1 + m, inf);
    for(int i = 1; i <= 1002; i++){
        for(int j = 1; j <= 1002; j++){
            v[i][j] = inf;
        }
    }
    fill(tem + 1, tem + 1 + n, -1);

    int a,b,c;
    for(int i = 1; i <= m; i++){
        scanf("%d %d %d",&a,&b,&c);
        v[a][b] = min(c,v[a][b]);
    }
    dijkstra(x);//x是起点

    int tt;
    //反向建图
    for(int i = 1; i <= n; i++){
        for(int j = 1; j < i; j++){
            tt = v[i][j];
            v[i][j] = v[j][i];
            v[j][i] = tt;
        }
    }
    dijkstra(x);
    int sum = 0;
    for(int i = 1; i <= n; i++){
        sum = max(dist[i] + tem[i],sum);
    }
    printf("%d\n",sum);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值