农场派对

农场派对

题目描述

\(N(1\leq N\leq1000)\)头牛要去参加一场在编号为\(x(1\leq x \leq N)\) 的牛的农场举行的派对。有 \(M(1\leq M \leq 100000)\)条有向道路,每条路长 \(T_i(1\leq T_i\leq100)\);每头牛都必须参加完派对后回到家,每头牛都会选择最短路径。求这\(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是一样的

猜你喜欢

转载自www.cnblogs.com/LeafLove/p/12807135.html