37 最短路的变式(这里求最长路)

链接:https://www.nowcoder.com/acm/contest/188/C
来源:牛客网
 

小w不会离散数学,所以她van的图论游戏是送分的

小w有一张n个点n-1条边的无向联通图,每个点编号为1~n,每条边都有一个长度
小w现在在点x上
她想知道从点x出发经过每个点至少一次,最少需要走多少路

输入描述:

第一行两个整数 n,x,代表点数,和小w所处的位置
第二到第n行,每行三个整数 u,v,w,表示u和v之间有一条长为w的道路

输出描述:

一个数表示答案

 

示例1

输入

复制

3 1
1 2 1
2 3 1

输出

复制

2

备注:

1 ≤ n ≤ 50000 , 1 ≤ w ≤ 2147483647

题目的意思很简单就是让你一次性跑完所有的点然后求算一下,这个人要走的最短距离,讲过画几个图之后会发现,mindis=所有边权和的二倍然后减掉最长的那条边就是答案,因为你要跑完所有的边所以就会有些边一定要跑两次,有一些边不需要跑两次,因为我们想要我们的距离跑的最短吗,所以就是我们让那一条最长的边就跑一次就是我们我们要的最优解了;

#include <bits/stdc++.h>
using namespace std;
const int Max = 1e6+10;
typedef long long ll;
#define rep(i,s,n) for(ll i=s;i<=n;i++)
#define per(i,n,s) for(ll i=n;i>=s;i--)
struct node{
    ll u,v,w,next;
}Edge[Max<<1];

ll head[Max],sum,max1,n,s,to,dis[Max];
bool visited[Max];

void add(ll u, ll v, ll w){
     Edge[to].v=v;
     Edge[to].w=w;
     Edge[to].next=head[u];
     Edge[to].u=u;
     head[u]=to++;
}
ll q[Max];
void spfa(){
     visited[s]=true;
     int front1=0,rearl=0;
     q[rearl++]=s;
     while(rearl>front1){
        ll u=q[front1++];
        for(int i=head[u];i!=-1;i=Edge[i].next){
            int v=Edge[i].v;
            if(dis[v]<dis[u]+Edge[i].w&&!visited[v]){
             dis[v]=dis[u]+Edge[i].w;
             if(dis[v]>max1) {
                max1=dis[v];
             }
             if(!visited[v]){
                q[rearl++]=v;
                visited[v]=true;
             }
            }
        }
     }
}
int main(){

   scanf("%lld %lld",&n,&s);
   rep(i,0,n) head[i]=-1;
   rep(i,1,n-1){
     ll u,v,w;
     scanf("%lld %lld %lld",&u,&v,&w);
     add(u,v,w);
     add(v,u,w);
     sum+=w;
   }
   max1=0;
   spfa();
   printf("%lld\n",sum*2-max1);
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值