我不黑博士

69 篇文章 0 订阅

我不黑博士


问题描述

在纠结了很久之后,博士终于决定约某个女生出来爬山(你们可以咨询我这个人的名字是什么,我可以免费告诉你哟,亲! ).
博士所在的城市特别奇怪,任何两个居住点之间有且仅有一条通路(其实这是方便博士遍历所有的路径来找后宫).
他决定先去接这个女生,然后再跟女生一起去爬山.
可是女生却不愿意告诉博士她到底在哪里(博士又被调戏了囧),她只是告诉了博士两个居住点,而她就在这两个居住点中的任意一个.
博士决定先去距离他所在的居住点近的一个居住点,如果女生不在这个居住点,他再去另外一个居住点接女生.
现在博士很好奇,如果不知道他所在的具体位置,也不知道女生告诉博士的两个居住点的具体位置,博士最坏情况下要走多远?


输入

输入文件名为 BlackBS.in。 (我不黑博士,对吧?)
输入第一行两个正整数 N M
分别表示博士所在城市的楼房数和街道数。
下接 M 行,每行 3 个正整数 Xi , Yi , Zi ,描述一条从 Xi Yi 的长度为 Zi 的街道。


输出

输出文件名为 BlackBS.out。
输出一行一个正整数,为最坏情况下博士要走的距离。


输入样例

4 3
1 2 1
2 3 1
3 4 1


输出样例

4


数据范围

对于 20% 的数据, n<=100 ; m<=10000 ; 每条街道的长度 <=100 <script type="math/tex" id="MathJax-Element-266"><=100</script>;
对于 100% 的数据, n<=200000 ; m<=2000000 ; 每条街道的长度 <=100000 <script type="math/tex" id="MathJax-Element-270"><=100000</script>.


Solution

求出树的直径,其两段即为女生的居住点;
然后枚举博士所在的位置,更新最大值即可。


Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
#define LL long long

using namespace std;

int n,m,l,r,cnt;
LL maxn;

int head[200010],nxt[4000010],data[4000010],flow[4000010];
LL dis[200010],dis2[200010];
bool in_stack[200010];
queue<int>q;

void add(int x,int y,int z){
    nxt[cnt]=head[x];data[cnt]=y;flow[cnt]=z;head[x]=cnt++;
    nxt[cnt]=head[y];data[cnt]=x;flow[cnt]=z;head[y]=cnt++; 
}

void spfa(int s){
    dis[s]=0;
    in_stack[s]=true;
    q.push(s);
    while(!q.empty()){
        int now=q.front();
        q.pop();
        in_stack[now]=false;
        for(int i=head[now];i!=-1;i=nxt[i])
            if(dis[data[i]]>dis[now]+flow[i]){
                dis[data[i]]=dis[now]+flow[i];
                if(!in_stack[data[i]]){
                    in_stack[data[i]]=true;
                    q.push(data[i]);
                }
            }
    }
}

void spfa2(int s){
    dis2[s]=0;
    in_stack[s]=true;
    q.push(s);
    while(!q.empty()){
        int now=q.front();
        q.pop();
        in_stack[now]=false;
        for(int i=head[now];i!=-1;i=nxt[i])
            if(dis2[data[i]]>dis2[now]+flow[i]){
                dis2[data[i]]=dis2[now]+flow[i];
                if(!in_stack[data[i]]){
                    in_stack[data[i]]=true;
                    q.push(data[i]);
                }
            }
    }
}

int main(){

    freopen("blackbs.in","r",stdin);
    freopen("blackbs.out","w",stdout);

    memset(head,-1,sizeof head);

    scanf("%d%d",&n,&m);

    for(int i=1;i<=m;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z); 
    }

    memset(dis,0x3f,sizeof dis);maxn=-dis[0];
    spfa(1);

    for(int i=1;i<=n;i++)
        if(dis[i]>maxn){
            maxn=dis[i];
            l=i;
        }

    memset(dis,0x3f,sizeof dis);maxn=-dis[0];
    spfa(l);

    for(int i=1;i<=n;i++)
        if(dis[i]>maxn){
            maxn=dis[i];
            r=i;
        }

    memset(dis2,0x3f,sizeof dis2);maxn=-dis2[0];
    spfa2(r);

    for(int i=1;i<=n;i++)
        maxn=Max(maxn,Min(dis2[i],dis[i]));

    printf("%lld\n",maxn+dis[r]);

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值