传送门


强行二合一最为致命

第一问直接最短路+$DFS$解决

考虑第二问,与深度相关,可以考虑长链剖分。

设$f_{i,j}$表示长度为$i$,经过边数为$j$时的最大边权和,考虑到每一次从重儿子转移过来的时候,不仅要将$f$数组右移一格,还需要同时加上一个值。显然用线段树等数据结构额外维护是不现实的,我们考虑维护一个影响范围为整个$f_i$的加法标记$tag_i$,将$f_{i,0}$设置为$-tag_i$,每一次上传的时候把标记也一起上传,合并轻儿子、计算答案的时候将这个$tag$加上,就能够做到快速地维护了。

长链剖分代码比点分治还长……

 #include<bits/stdc++.h>
 #define P pair < int , int >
 #define int long long
 //This code is written by Itst
 using namespace std;

 inline int read(){
     ;
     ;
     char c = getchar();
     while(c != EOF && !isdigit(c)){
         if(c == '-')
             f = ;
         c = getchar();
     }
     while(c != EOF && isdigit(c)){
         a = (a << ) + (a << ) + (c ^ ');
         c = getchar();
     }
     return f ? -a : a;
 }

 ;
 vector < P > e[MAXN];
 struct edge{
     int end , upEd , w;
 }Ed[MAXN << ];
 ] , g[MAXN << ] , sz[MAXN] , tag[MAXN] , *dp[MAXN] , *cnt[MAXN];
 int *p1 = f , *p2 = g , N , M , K , cntEd , ans , times;
 priority_queue < P > q;
 bool vis[MAXN];

 inline void addEd(int a , int b , int c){
     Ed[++cntEd].end = b;
     Ed[cntEd].upEd = head[a];
     Ed[cntEd].w = c;
     head[a] = cntEd;
 }

 void Dijk(){
     q.push(P( , ));
     memset(dis , 0x3f , sizeof(dis));
     dis[] = ;
     while(!q.empty()){
         P t = q.top();
         q.pop();
         if(-t.first > dis[t.second])
             continue;
          ; i < sz[t.second] ; ++i)
             if(dis[e[t.second][i].first] > dis[t.second] + e[t.second][i].second){
                 dis[e[t.second][i].first] = dis[t.second] + e[t.second][i].second;
                 q.push(P(-dis[e[t.second][i].first] , e[t.second][i].first));
             }
     }
 }

 void create(int now){
     vis[now] = ;
      ; i < sz[now] ; ++i)
         if(!vis[e[now][i].first] && dis[e[now][i].first] == dis[now] + e[now][i].second){
             addEd(now , e[now][i].first , e[now][i].second);
             addEd(e[now][i].first , now , e[now][i].second);
             create(e[now][i].first);
         }
 }

 void dfs1(int now , int pre){
     md[now] = dep[now] = dep[pre] + ;
     for(int i = head[now] ; i ; i = Ed[i].upEd)
         if(!dep[Ed[i].end]){
             dfs1(Ed[i].end , now);
             if(md[Ed[i].end] > md[now]){
                 md[now] = md[Ed[i].end];
                 son[now] = Ed[i].end;
                 len[now] = Ed[i].w;
             }
         }
 }

 void dfs2(int now){
     if(son[now]){
         dp[son[now]] = dp[now] + ;
         cnt[son[now]] = cnt[now] + ;
         dfs2(son[now]);
         tag[now] = tag[son[now]] + len[now];
         dp[now][] = -tag[now];
     }
     cnt[now][] = ;
     if(ans < dp[now][K] + tag[now]){
         ans = dp[now][K] + tag[now];
         times = cnt[now][K];
     }
     else
         if(ans == dp[now][K] + tag[now])
             times += cnt[now][K];
     for(int i = head[now] ; i ; i = Ed[i].upEd)
          && Ed[i].end != son[now]){
             dp[Ed[i].end] = p1;
             cnt[Ed[i].end] = p2;
             p1 += (md[Ed[i].end] - dep[Ed[i].end] + ) << ;
             p2 += (md[Ed[i].end] - dep[Ed[i].end] + ) << ;
             dfs2(Ed[i].end);
              ; j <= md[Ed[i].end] - dep[Ed[i].end] && j <= K -  ; ++j)
                  - j)
                      - j] + Ed[i].w){
                         ans = tag[Ed[i].end] + dp[Ed[i].end][j] + tag[now] + dp[now][K -  - j] + Ed[i].w;
                         times = cnt[Ed[i].end][j] * cnt[now][K -  - j];
                     }
                     else
                          - j] + Ed[i].w)
                             times += cnt[Ed[i].end][j] * cnt[now][K -  - j];
              ; j <= md[Ed[i].end] - dep[Ed[i].end] +  && j <= K ; ++j)
                 ] + tag[Ed[i].end] + Ed[i].w - tag[now]){
                     dp[now][j] = dp[Ed[i].end][j - ] + tag[Ed[i].end] + Ed[i].w - tag[now];
                     cnt[now][j] = cnt[Ed[i].end][j - ];
                 }
                 else
                     ] + tag[Ed[i].end] + Ed[i].w - tag[now])
                         cnt[now][j] += cnt[Ed[i].end][j - ];
         }
 }

 signed main(){
 #ifndef ONLINE_JUDGE
     freopen("2993.in" , "r" , stdin);
     //freopen("2993.out" , "w" , stdout);
 #endif
     N = read();
     M = read();
     K = read() - ;
      ; i <= M ; ++i){
         int a = read() , b = read() , c = read();
         e[a].push_back(P(b , c));
         e[b].push_back(P(a , c));
         ++sz[a];
         ++sz[b];
     }
      ; i <= N ; ++i)
         sort(e[i].begin() , e[i].end());
     Dijk();
     create();
     dfs1( , );
     dp[] = p1;
     p1 += md[] << ;
     cnt[] = p2;
     p2 += md[] << ;
     dfs2();
     cout << ans << ' ' << times;
     ;
 }

Luogu2993 FJOI2014 最短路径树问题 最短路树、长链剖分的更多相关文章

  1. (持续更新)虚树,KD-Tree,长链剖分,后缀数组,后缀自动机

    真的就是讲课两天,吸收一个月呢! \(1.\)虚树 \(2.\)KD-Tree \(3.\)长链剖分 \(4.\)后缀数组 后缀数组 \(5.\)后缀自动机 后缀自动机

  2. [FJOI2014]最短路径树问题 长链剖分

    [FJOI2014]最短路径树问题 LG传送门 B站传送门 长链剖分练手好题. 如果你还不会长链剖分的基本操作,可以看看我的总结. 这题本来出的很没水平,就是dijkstra(反正我是不用SPFA)的 ...

  3. Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)

    题面 Bzoj 洛谷 题解 首先把最短路径树建出来(用\(Dijkstra\),没试过\(SPFA\)\(\leftarrow\)它死了),然后问题就变成了一个关于深度的问题,可以用长链剖分做,所以我 ...

  4. bzoj 4016 [FJOI2014]最短路径树问题(最短路径树+树分治)

    4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 426  Solved: 147[Submit][Stat ...

  5. BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治

    BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治 Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择 ...

  6. 洛谷 [FJOI2014]最短路径树问题 解题报告

    [FJOI2014]最短路径树问题 题目描述 给一个包含\(n\)个点,\(m\)条边的无向连通图.从顶点\(1\)出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多 ...

  7. [BZOJ4016][FJOI2014]最短路径树问题

    [BZOJ4016][FJOI2014]最短路径树问题 试题描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长 ...

  8. [BZOJ4016][FJOI2014]最短路径树问题(dijkstra+点分治)

    4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 1796  Solved: 625[Submit][Sta ...

  9. 【BZOJ4016】[FJOI2014]最短路径树问题 最短路径树+点分治

    [BZOJ4016][FJOI2014]最短路径树问题 Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径 ...

随机推荐

  1. 【读书笔记】iOS-深入解剖对等网络

    协议本身是一个运行在UDP之上的定制协议.我所以决定使用一个定制协议很简单.首先,当前这个任务看起来足够简单,因此与尝试改进一个现在协议相比,直接构建一个定制协议更为容易.其次,定制协议可以将开销减少 ...

  2. hosts 文件

    各系统平台hosts文件存放路径 路径如下: Windows系统: C:\Windows\System32\drivers\etc\hosts        Linux系统:/etc/hosts    ...

  3. WebGL学习笔记(一)

    作者:朱金灿 来源:http://blog.csdn.net/clever101 (一)WebGL是什么? WebGL是一门在网页上显示三维图形的技术,你可以把它理解为把OpenGL从C/S端搬到了B ...

  4. Salesforce Live Agent 简介

    Live Agent Salesforce 内置了即时聊天功能--Live Agent,可以用来作为客服工具. 本文简单介绍了使用 Live Agent 的步骤,主要包含: 启用 Live Agent ...

  5. (网页)Uncaught ReferenceError: pageImport is not defined

    在js开发中,很多人遇到类似问题,都找不到解决方法.Uncaught ReferenceError: $ is not defined,在这里给大家提供几个解决方法. 1.出现这个错误,最可能的是引用 ...

  6. maven(三):maven项目结构及其运行机制

    在上一篇中讲了如何创建maven项目,现在回到那个项目 项目结构 src/main/java:java代码目录 src/main/resources:资源目录,比如spring.xml文件,prope ...

  7. entity framework异常 The specified cast from a materialized 'System.Int32' type to the 'System.String' type is not valid

    ROW_NUMBER() OVER (ORDER BY (select Null)) AS Id entity framework 查询中有这句会有异常

  8. OpenCV 的颜色空间转换

    # coding: utf-8 ''' 第13章主要介绍:颜色空间转换 ''' import cv2 import numpy as np ''' 经常用到的颜色空间转换是: BGR<-> ...

  9. 解决Windows10或者其他版本Windows Update报错的问题

    最近更新系统,发现报错0x80248014,系统版本为redstone2(创意者更新). 总结发现,只要是windows各个版本自动更新报错的,如0x80开头的一系列错误,都可以通过如下步骤解决: 手 ...

  10. Deepin中设置文件或文件夹权限

    Deepin中设置文件或文件夹权限 -R 递归进行某项操作,不论是删除文件夹或者修改文件夹下所有文件权限   权限更改,777相当于完全控制权限: 更改一个文件夹或文件的权限:chmod 777 文件 ...