牛客网牛客练习赛27 水图

链接
思路:
重链走一次,轻链走两次
用spfa求出该点到所有点的路径(也就是说所有的链的权值已经求出来)
求出来后减去这些路径中的最大值即可

/* 链式前向星SPFA最短路算法*/
#include<iostream>
#include<queue>
#include <algorithm>
#include <stdio.h>
#include<cstring>
#define LL long long
using namespace std ;
const int maxn = 10050 ;
int N, M, head[maxn] ;
LL dis[maxn], cnt;
int vis[10500] ;
int n , m ;
struct Edge
{  LL cap ;
    int v,  next; // v 是去向 , cap 是流量(权值) next就不解释了
}e[100000];

void init()
{
    cnt = 0;
    memset(head, -1, sizeof (head));
    memset(dis , 0x3f , sizeof(dis)) ;
}

void  Addedge(int x, int y, LL z)
{

    e[cnt].v = y;
    e[cnt].cap = z;
    e[cnt].next = head[x];
    head[x] = cnt++;
}
 void spfa(int s){
   dis[s] = 0 ;
   queue<int> q ;
   q.push(s) ;
   while(!q.empty()){
     int u = q.front() ; q.pop() ;
      vis[u] = 0 ;
      for(int i = head[u] ; i != -1 ; i = e[i].next){
         int v = e[i].v ;
         LL w = e[i].cap ;
         if(dis[v] > w + dis[u] ) {
            dis[v] = w + dis[u] ;
            if(!vis[v]) { vis[v] = 1 ; q.push(v) ;}
         }
      }
   }
 }
int main(){
    cin >> n >> m ; // n个节点的树 , m为起点
    init() ;
    LL ans = 0 ;
    memset(vis , 0 , sizeof(vis) ) ;
    for(int i = 0 ; i < n-1 ; i++){
      int u , v ; LL w ;
      cin >> u >> v >>w ;
      ans += w*2 ;
      Addedge(u , v , w) ;
      Addedge(v , u , w) ;
    }
    spfa(m) ; LL maxn = 0 ;
   // cout << "ans = " << ans << endl ;
    for(int i = 1 ; i <= n ; i++){
        maxn = max(maxn , dis[i]) ;
     //   cout << dis[i] << endl ;
    }
    cout << ans - maxn << endl ;


 return 0 ;
}

猜你喜欢

转载自blog.csdn.net/qq_42894605/article/details/82808168