校内练习 华山论剑 [最短路]

Posted cytus

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了校内练习 华山论剑 [最短路]相关的知识,希望对你有一定的参考价值。

  

华山论剑

题目描述

话说数年一度的武林盛事“华山论剑”将至,东邪、西毒、南帝、北丐,老顽童等高手云集华山之巅,誓要分出究竟谁是武林至尊……
如此武林盛世,当然求围观。据统计,有n-1位同学想去华山看热闹,他们分别住在编号为1-n(除华山所在地x)的地方,华山编号为x(1<=x<=n)。现在有M(1<=m<=100000)条有向道路,每条路长为ti(1<=ti<=100)。
由于每位同学看完打架后还要回家吃饭,所以要选择最短路径,求这n-1位同学的最短路径(一个来回)中最长的一条的长度。
特别提醒:可能有权值不同的重边。
数据保证每位同学均能到达华山处,并从华山返回。


输入

第1行: n,m,x;
第2~m+1行: ai,bi,ti,表示有一条从ai到bi的路,长度为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

 

提示

对于60%的数据,满足 1<=n<=100
对于100%的数据,满足 1<=n<=1000。

  分析:
  并不难的最短路。
  分别正反向建边,然后正反跑两次最短路,再求两次最短路之和的最大值就行了。
  Code:
//It is made by HolseLee on 17th Aug 2018
//华山论剑
#include<bits/stdc++.h>
#define Max(a,b) (a)>(b)?(a):(b)
using namespace std;

const int N=1001;
const int M=1e5+7;
int n,m,tag,h1[N],h2[N],cnt1,cnt2,dis1[N],dis2[N],ans;
bool vis[N];
struct Node{
    int to,val,nxt;
}e1[M],e2[M];
queue<int>t;

inline int read()
{
    char ch=getchar();int num=0;bool flag=false;
    while(ch<0||ch>9){if(ch==-)flag=true;ch=getchar();}
    while(ch>=0&&ch<=9){num=num*10+ch-0;ch=getchar();}
    return flag?-num:num;
}

inline void add1(int x,int y,int z)
{
    e1[++cnt1].to=y;
    e1[cnt1].val=z;
    e1[cnt1].nxt=h1[x];
    h1[x]=cnt1;
}

inline void add2(int x,int y,int z)
{
    e2[++cnt2].to=y;
    e2[cnt2].val=z;
    e2[cnt2].nxt=h2[x];
    h2[x]=cnt2;
}

void spfa1()
{
    memset(vis,0,sizeof(vis));
    memset(dis1,0x7f,sizeof(dis1));
    while(!t.empty())t.pop();
    dis1[tag]=0;vis[tag]=1;
    t.push(tag);
    int x,y;
    while(!t.empty()){
        x=t.front();t.pop();
        vis[x]=0;
        for(int i=h1[x];i!=-1;i=e1[i].nxt){
            y=e1[i].to;
            if(dis1[y]>dis1[x]+e1[i].val){
                dis1[y]=dis1[x]+e1[i].val;
                if(!vis[y])t.push(y),vis[y]=1;
            }
        }
    }
}

void spfa2()
{
    memset(vis,0,sizeof(vis));
    memset(dis2,0x7f,sizeof(dis2));
    while(!t.empty())t.pop();
    dis2[tag]=0;vis[tag]=1;
    t.push(tag);
    int x,y;
    while(!t.empty()){
        x=t.front();t.pop();
        vis[x]=0;
        for(int i=h2[x];i!=-1;i=e2[i].nxt){
            y=e2[i].to;
            if(dis2[y]>dis2[x]+e2[i].val){
                dis2[y]=dis2[x]+e2[i].val;
                if(!vis[y])t.push(y),vis[y]=1;
            }
        }
    }
}

int main()
{
    n=read();m=read();tag=read();
    memset(h1,-1,sizeof(h1));
    memset(h2,-1,sizeof(h2));
    int x,y,z;
    for(int i=1;i<=m;++i){
        x=read();y=read();z=read();
        add1(x,y,z);add2(y,x,z);
    }
    spfa1();spfa2();
    for(int i=1;i<=n;++i){
        ans=Max(ans,dis1[i]+dis2[i]);
    }
    printf("%d
",ans);
    return 0;
}

 

以上是关于校内练习 华山论剑 [最短路]的主要内容,如果未能解决你的问题,请参考以下文章

校内训练2019-11-15表演

每日一学|最短路径:Dijkstra 算法和 Floyd 算法

poj-2253_最短路练习

LGOJ5651基础最短路练习题

牛客练习-凤凰——不同寻常的最短路(找规律求结点数)

最短路练习