zoukankan      html  css  js  c++  java
  • 农场派对

    农场派对

    题目描述

    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;
    }
    
    海到无边天作岸,山登绝顶我为峰
  • 相关阅读:
    Linux 配置 nginx + php
    Laravel 网站项目目录结构规划
    配置服务器 Ubuntu 记录+踩坑
    JavaScript 单例,Hash,抛异常
    易理解版八皇后
    获取bing每日图片
    OpenGL 学习笔记 01 环境配置
    [瞎JB写] C++多态
    c++ initialize_list
    最长上升子序列的二分优化
  • 原文地址:https://www.cnblogs.com/Fiona0726/p/12812627.html
Copyright © 2011-2022 走看看