农场派对

农场派对

题目描述

N(1≤N≤1000)头牛要去参加一场在编号为x(1≤x≤N)的牛的农场举行的派对。有M(1≤M≤100000)条有向道路,每条路长Ti(1≤Ti≤100);每头牛都必须参加完派对后回到家,每头牛都会选择最短路径。求这N头牛的最短路径(一个来回)中最长的一条的长度。特别提醒:可能有权值不同的重边。

输入

第1行:3个空格分开的整数N,M,X;
第2…M+1行:3个空格分开的整数Ai,Bi,Ti,表示有一条从AiBi的路,长度为Ti。

输出

一行一个数,表示最长最短路的长度。

样例输入

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

样例输出

10

解题思路

牛牛的一个来回只需跑两趟spfa即可。第一遍spfa求出去农场的最短路,然后将边的方向调转(这里采用矩阵转置的方法),再跑一遍spfa即可得到回的最短路,相加便是一次来回的最短路径长度。

代码

#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
#define MAXN 1005
#define INF 0x3f3f3f3f

int n,m,x;
int d[MAXN][MAXN], dis1[MAXN], dis2[MAXN];
bool vis[MAXN];
vector<int> edge[MAXN];

void init(void){
    scanf("%d%d%d",&n,&m,&x);
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j) d[i][j] = INF;
        d[i][i] = 0;
        vis[i] = false;
        dis1[i] = dis2[i] = INF;
    }
    for(int i=0;i<m;++i){
        int a,b,t;
        scanf("%d%d%d",&a,&b,&t);
        if(d[a][b] > t) d[a][b] = t;    //去重边,选择最短的边
    }
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            if(i!=j && d[i][j]!=INF) edge[i].push_back(j);
}
void trans(void){   //矩阵转置
    for(int i=1;i<=n;++i){
        for(int j=1;j<i;++j){
            int tmp = d[i][j];
            d[i][j] = d[j][i];
            d[j][i] = tmp;
        }
    }
    for(int i=1;i<=n;++i) edge[i].clear();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            if(i!=j && d[i][j]!=INF) edge[i].push_back(j);
}
void spfa(int u,int dis[]){     //dis采用参数传递,这样只需写一个spfa即可
    dis[u] = 0; vis[u] = true;
    queue<int> Q;
    Q.push(u);
    while(Q.size()){
        int x = Q.front(); Q.pop();
        vis[x] = false;
        int len = edge[x].size();
        for(int i=0;i<len;++i){
            int y = edge[x][i], z = d[x][y];
            if(dis[y] > dis[x]+z){
                dis[y] = dis[x]+z;
                if(!vis[y]) Q.push(y), vis[y] = true;
            }
        }
    }
}

int main(void)
{
    init();
    spfa(x,dis1);
    trans();
    spfa(x,dis2);
    int ans = 0;
    for(int i=1;i<=n;++i) ans = max(ans,dis1[i]+dis2[i]);
    printf("%d",ans);
    return 0;
}
posted @ 2020-05-01 09:48  凰琊  阅读(289)  评论(0编辑  收藏  举报