• 农场派对


    农场派对

    题目描述

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

    输入描述

    (1)行: (3)个空格分开的整数 (N,M,X)

    (2.....M+1)行:(3)个空格分开的整数(A_i,B_i,T_i) ,表示有一条从(A_i)(B_i)的路,长度为 (T_i)

    输出描述

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

    样例输入

    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
    

    思路

    本来在数据范围比较小的情况下,可以直接跑floyd算法,然后结算回路最大长度即可,但是在1000下时间复杂度(O(n^3))要运行(1e9)次,对于大多数情况下显然是不可以的(除了某些强的不行的OJ)。所以这里考虑用Dijkstra,来计算单源最短路,然后将边的方向调转,再计算一次单源最短路,就得出了去和回来的最短路径,相加即为来回的回路的最短长度,最后(O(N))寻找最大值即可。

    代码

    /****************************************************
    /@Author: Kirito
    /@TIME:   2020-04-30
    /@FILENAME: partyatformzhengjie.cpp
    /@REMARK:    
    /****************************************************/
    #include <bits/stdc++.h>
    #define lowbit(x) (x&(-x))
    #define CSE(x,y) memset(x,y,sizeof(x))
    #define INF 0x3f3f3f3f
    #define Abs(x) (x>=0?x:(-x))
    #define FAST ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    
    typedef long long ll;
    typedef pair<int,int> pii;
    typedef pair<ll , ll> pll;
    
    const int maxn=211111;
    //graph1
    int first[maxn],nxt1[maxn],u[maxn],v[maxn];
    int mpp[1005][1005],n,m,s,cnt1;
    //graph2
    int head[maxn],nxt2[maxn],l[maxn],r[maxn];
    int mpw[1005][1005],cnt2;
    //spfa-box
    int dist1[maxn],book[maxn],dist2[maxn];
    //邻接表
    void add(int x,int y){
        cnt1++;cnt2++;
        u[cnt1]=x;v[cnt1]=y;l[cnt2]=y;r[cnt2]=x;
        nxt1[cnt1]=first[u[cnt1]];first[u[cnt1]]=cnt1;
        nxt2[cnt2]=head[l[cnt2]];head[l[cnt2]]=cnt2;
        return;
    }
    
    void spfa1(){
        CSE(dist1,INF);CSE(book,0);
        queue<int>point;
        dist1[s]=0;book[s]=1;point.push(s);
        while(!point.empty()){
            int x=point.front();point.pop();book[x]=0;
            for(int i=first[x];i!=-1;i=nxt1[i]){
                //可加判断是否wu解
                int y=v[i],w=mpp[x][y];
                if(dist1[y]>dist1[x]+w){
                    dist1[y]=dist1[x]+w;
                    if(!book[y]){
                        point.push(y);book[y]=1;
                    }
                }
            }
        }
        return;
    }
    
    void spfa2(){
        CSE(dist2,INF);CSE(book,0);
        queue<int>point;
        dist2[s]=0;book[s]=1;point.push(s);
        while(!point.empty()){
            int x=point.front();point.pop();book[x]=0;
            for(int i=head[x];i!=-1;i=nxt2[i]){
                //可加判断是否wu解
                int y=r[i],w=mpw[x][y];
                if(dist2[y]>dist2[x]+w){
                    dist2[y]=dist2[x]+w;
                    if(!book[y]){
                        point.push(y);book[y]=1;
                    }
                }
            }
        }
        return;
    }
    
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("in.in","r",stdin);
    #endif
        FAST;
        cin>>n>>m>>s;
        CSE(first,-1);CSE(nxt1,-1);CSE(nxt2,-1);CSE(head,-1);
        CSE(mpp,INF);CSE(mpw,INF);
        for(int i=0;i<m;i++){
            int x,y,w;
            cin>>x>>y>>w;
            if(w<mpp[x][y]){
                mpp[x][y]=w;
                add(x,y);
                mpw[y][x]=w;
            }
        }
        spfa1();spfa2();
        int ans=0;
        for(int i=1;i<=n;i++){
            ans=max(ans,dist1[i]+dist2[i]);
        }
        cout<<ans<<endl;
        return 0;
    }
    

    代码中用的是spfa算法,道理和Dijkstra是一样的

  • 相关阅读:
    常用汇编指令大全
    Qt信号槽-连接方式
    QtAssiant-QComboBox
    解决Qt-至少需要一个有效且已启用的储存库 问题
    qt插件化开发
    qml----定位信息
    多媒体(音乐、视频播放器,相机)
    qml----Model/View入门(九)Repeater
    qml----Model/View入门(八)PathView
    qml----Model/View入门(七)GridView
  • 原文地址:https://www.cnblogs.com/LeafLove/p/12807135.html
Copyright © 2020-2023  润新知