Luogu2993 FJOI2014 最短路径树问题 最短路树、长链剖分
强行二合一最为致命
第一问直接最短路+$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 最短路径树问题 最短路树、长链剖分的更多相关文章
- (持续更新)虚树,KD-Tree,长链剖分,后缀数组,后缀自动机
真的就是讲课两天,吸收一个月呢! \(1.\)虚树 \(2.\)KD-Tree \(3.\)长链剖分 \(4.\)后缀数组 后缀数组 \(5.\)后缀自动机 后缀自动机
- [FJOI2014]最短路径树问题 长链剖分
[FJOI2014]最短路径树问题 LG传送门 B站传送门 长链剖分练手好题. 如果你还不会长链剖分的基本操作,可以看看我的总结. 这题本来出的很没水平,就是dijkstra(反正我是不用SPFA)的 ...
- Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)
题面 Bzoj 洛谷 题解 首先把最短路径树建出来(用\(Dijkstra\),没试过\(SPFA\)\(\leftarrow\)它死了),然后问题就变成了一个关于深度的问题,可以用长链剖分做,所以我 ...
- bzoj 4016 [FJOI2014]最短路径树问题(最短路径树+树分治)
4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 426 Solved: 147[Submit][Stat ...
- BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治
BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治 Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择 ...
- 洛谷 [FJOI2014]最短路径树问题 解题报告
[FJOI2014]最短路径树问题 题目描述 给一个包含\(n\)个点,\(m\)条边的无向连通图.从顶点\(1\)出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多 ...
- [BZOJ4016][FJOI2014]最短路径树问题
[BZOJ4016][FJOI2014]最短路径树问题 试题描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长 ...
- [BZOJ4016][FJOI2014]最短路径树问题(dijkstra+点分治)
4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 1796 Solved: 625[Submit][Sta ...
- 【BZOJ4016】[FJOI2014]最短路径树问题 最短路径树+点分治
[BZOJ4016][FJOI2014]最短路径树问题 Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径 ...
随机推荐
- 【读书笔记】iOS-属性
assign:简单的赋值. retain:赋值之后,会调用新的retain方法和旧值的release方法. copy:表示先将值拷贝一份,然后,将这个拷贝赋值给实例变量,这个修饰词只适用于实现了NSC ...
- Apktool(1)——Apktool的安装
Apktool是google提供的apk的编译工具,有了它就可以做很多事情.比如获取apk的源码,apk汉化,对手机rom包做一些美化. 首先来看看apktool的安装(配置): 以下内容主要翻译字A ...
- (网页)HTML小技巧的一些小技巧
转自CSDN: 1.怎样定义网页语言(字符集)? 在制作网页过程中,你首先要定义网页语言,以便访问者浏览器自动设置语言,而我们用所见即所得的HTML工具时,都没有注意到这个问题, ...
- OpenCV 的颜色空间转换
# coding: utf-8 ''' 第13章主要介绍:颜色空间转换 ''' import cv2 import numpy as np ''' 经常用到的颜色空间转换是: BGR<-> ...
- 【Excel】SUMIF函数的兼容性
兼容性非常强的两个函数 SUMIF() 说兼容性,当然得说SUMIF了. 来,我们先举个例子. 现有一个表格,算起来只有"科目划分"."发生额"两列内容,但是折 ...
- asp.net mvc项目使用spring.net发布到IIS后,在访问提示错误 Could not load type from string value 'DALMsSql.DBSessionFactory,DALMsSql'.
asp.net mvc项目使用spring.net发布到IIS后,在访问提示错误 Could not load type from string value 'DALMsSql.DBSessionFa ...
- apply 和call 的区别,apply实用小技巧
Js apply方法详解 我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...
- Markdown图片存储解决方法-利用阿里云OSS
我们在用markdown写一些博客或者文章的时候,常常需要引用一些图片,一般都是找一个免费的图床上传,然后复制图片链接在我们的markdown文章中.类似像这样: 存在的隐患 一般的免费图片托管网站有 ...
- (转)Python网络爬虫实战:世纪佳缘爬取近6万条数据
又是一年双十一了,不知道从什么时候开始,双十一从“光棍节”变成了“双十一购物狂欢节”,最后一个属于单身狗的节日也成功被攻陷,成为了情侣们送礼物秀恩爱的节日. 翻着安静到死寂的聊天列表,我忽然惊醒,不行 ...
- swift 该死的派发机制--待完成
swift 该死的派发机制 final static oc类型 多态类型 静态类型 动态函数 静态函数 nsobject: 1.缺省不再使用oc的动态派发机制: 2.可以使用nsobject暴露出来 ...