• Evanyou Blog 彩带


      

    华山论剑

    题目描述

    话说数年一度的武林盛事“华山论剑”将至,东邪、西毒、南帝、北丐,老顽童等高手云集华山之巅,誓要分出究竟谁是武林至尊……
    如此武林盛世,当然求围观。据统计,有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;
    }
  • 相关阅读:
    教你取得计算机的所有权(可删除和打开或复制系统文件)
    为什么人口红利不能解决中国危机?
    开发者需要知道的11条HTML5小常识
    高性能CSS(四)
    8个应该去逛逛JQuery的学习网站
    用PHP调用证件识别接口识别本地图片
    Android开发有用的三方网站
    手机话费充值和手机流量充值 API
    Android开发之短信验证码示例
    微信小程序(应用号)开发新闻客户端的实战课程
  • 原文地址:https://www.cnblogs.com/cytus/p/9494979.html
Copyright © 2020-2023  润新知