【BZOJ4016】[FJOI2014]最短路径树问题

题面

bzoj

洛谷

题解

虽然调了蛮久,但是思路还是蛮简单的2333

把最短路径树构出来,然后点分治就好啦

ps:如果树构萎了,这组数据可以卡掉

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
const int MAX_N = 3e4 + 5;
const int MAX_M = 6e4 + 5;
const int INF = 1e9;
int N, M, K;
struct Graph { int to, next, cost; } e[MAX_M << 2];
int fir1[MAX_N], fir2[MAX_N], e_cnt;
void clearGraph() {
memset(fir1, -1, sizeof(fir1));
memset(fir2, -1, sizeof(fir2));
e_cnt = 0;
}
void Add_Edge(int *fir, int u, int v, int w) { e[e_cnt] = (Graph){v, fir[u], w}; fir[u] = e_cnt++; }
vector<int> vec[MAX_N];
bool vis[MAX_N];
bool cmp(int i, int j) { return e[i].to < e[j].to; }
void dijkstra() {
static priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > que;
static int dis[MAX_N];
fill(&dis[1], &dis[N + 1], INF);
dis[1] = 0, que.push(make_pair(0, 1));
while (!que.empty()) {
pair<int, int> p = que.top(); que.pop();
int x = p.second;
if (p.first > dis[x]) continue;
for (int i = fir1[x]; ~i; i = e[i].next) {
int v = e[i].to;
if (dis[v] + e[i].cost == dis[x]) vec[v].push_back(i ^ 1);
}
for (int i = fir1[x]; ~i; i = e[i].next) {
int v = e[i].to;
if (dis[x] + e[i].cost < dis[v]) {
dis[v] = dis[x] + e[i].cost;
que.push(make_pair(dis[v], v));
}
}
}
}
void dfs(int x) {
vis[x] = 1;
sort(vec[x].begin(), vec[x].end(), cmp);
for (int i = 0, sz = vec[x].size(); i < sz; i++) {
int j = vec[x][i]; if (vis[e[j].to]) continue;
Add_Edge(fir2, x, e[j].to, e[j].cost), Add_Edge(fir2, e[j].to, x, e[j].cost);
dfs(e[j].to);
}
}
bool used[MAX_N];
int size[MAX_N], dep[MAX_N], dis[MAX_N], centroid, sz, rmx, mx;
int stk[MAX_N], top = 0;
int ans1 = 0, ans2 = 0;
void search_centroid(int x, int fa) {
size[x] = 1;
int mx = 0;
for (int i = fir2[x]; ~i; i = e[i].next) {
int v = e[i].to;
if (v == fa || used[v]) continue;
search_centroid(v, x);
size[x] += size[v];
mx = max(mx, size[v]);
}
mx = max(mx, sz - size[x]);
if (mx < rmx) centroid = x, rmx = mx;
}
namespace cpp1 {
int bln[MAX_N];
void getans(int x, int fa) {
if (dep[x] < K - 1) ans1 = max(ans1, bln[K - 1 - dep[x]] + dis[x]);
for (int i = fir2[x]; ~i; i = e[i].next) {
int v = e[i].to; if (used[v] || v == fa) continue;
dep[v] = dep[x] + 1;
dis[v] = dis[x] + e[i].cost;
getans(v, x);
}
}
void getdis(int x, int fa) {
stk[++top] = x; bln[dep[x]] = max(bln[dep[x]], dis[x]);
for (int i = fir2[x]; ~i; i = e[i].next) {
int v = e[i].to; if (used[v] || v == fa) continue;
getdis(v, x);
}
}
void Div(int x) {
used[x] = 1; top = 0;
for (int i = fir2[x]; ~i; i = e[i].next) {
int v = e[i].to; if (used[v]) continue;
dep[v] = 1, dis[v] = e[i].cost;
getans(v, 0), getdis(v, 0);
}
ans1 = max(ans1, bln[K - 1]);
for (int i = 1; i <= top; i++) bln[dep[stk[i]]] = 0;
for (int i = fir2[x]; ~i; i = e[i].next) {
int v = e[i].to; if (used[v]) continue;
rmx = sz = size[v], centroid = 0;
search_centroid(v, 0);
Div(centroid);
}
}
}
namespace cpp2 {
map<pair<int, int>, int> mp;
void getans(int x, int fa) {
if (dep[x] < K - 1) ans2 += mp[make_pair(ans1 - dis[x], K - 1 - dep[x])];
for (int i = fir2[x]; ~i; i = e[i].next) {
int v = e[i].to; if (used[v] || v == fa) continue;
dep[v] = dep[x] + 1;
dis[v] = dis[x] + e[i].cost;
getans(v, x);
}
}
void getdis(int x, int fa) {
mp[make_pair(dis[x], dep[x])]++;
for (int i = fir2[x]; ~i; i = e[i].next) {
int v = e[i].to; if (used[v] || v == fa) continue;
getdis(v, x);
}
}
void Div(int x) {
used[x] = 1;
for (int i = fir2[x]; ~i; i = e[i].next) {
int v = e[i].to; if (used[v]) continue;
dep[v] = 1, dis[v] = e[i].cost;
getans(v, 0), getdis(v, 0);
}
ans2 += mp[make_pair(ans1, K - 1)];
mp.clear();
for (int i = fir2[x]; ~i; i = e[i].next) {
int v = e[i].to; if (used[v]) continue;
rmx = sz = size[v], centroid = 0;
search_centroid(v, 0);
Div(centroid);
}
}
}
int main () {
N = gi(), M = gi(), K = gi();
clearGraph();
for (int i = 1; i <= M; i++) {
int u = gi(), v = gi(), w = gi();
Add_Edge(fir1, u, v, w), Add_Edge(fir1, v, u, w);
}
dijkstra();
dfs(1);
sz = rmx = N;
search_centroid(1, 0);
cpp1::Div(centroid);
memset(used, 0, sizeof(used));
sz = rmx = N, centroid = 0;
search_centroid(1, 0);
cpp2::Div(centroid);
printf("%d %d\n", ans1, ans2);
return 0;
}

【BZOJ4016】[FJOI2014]最短路径树问题的更多相关文章

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

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

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

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

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

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

  4. 【BZOJ4016】[FJOI2014]最短路径树问题(点分治,最短路)

    [BZOJ4016][FJOI2014]最短路径树问题(点分治,最短路) 题面 BZOJ 洛谷 题解 首先把最短路径树给构建出来,然后直接点分治就行了. 这个东西似乎也可以长链剖分,然而没有必要. # ...

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

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

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

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

  7. 【BZOJ-4016】最短路径树问题 Dijkstra + 点分治

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

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

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

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

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

随机推荐

  1. Java虚拟机6:垃圾收集(GC)-1(内存溢出和内存泄漏的区别)

    1.前言 在进行垃圾收集之前需要普及几个比较重要的概念. 2.内存溢出和内存泄露的概念和区别: (1):内存溢出(out of memory):是指程序在申请内存时,没有足够的内存空间可以分配,系统不 ...

  2. 2241. [SDOI2011]打地鼠【暴力+剪枝】

    Description 打地鼠是这样的一个游戏:地面上有一些地鼠洞,地鼠们会不时从洞里探出头来很短时间后又缩回洞中.玩家的目标是在地鼠伸出头时,用锤子砸其头部,砸到的地鼠越多分数也就越高. 游戏中的锤 ...

  3. Hadoop学习之路(二十)MapReduce求TopN

    前言 在Hadoop中,排序是MapReduce的灵魂,MapTask和ReduceTask均会对数据按Key排序,这个操作是MR框架的默认行为,不管你的业务逻辑上是否需要这一操作. 技术点 MapR ...

  4. AWR报告分析

    AWR报告分析 awr报告是oracle 10g下提供的一种性能收集和分析工具,它能提供一个时间段内整个系统资源使用情况的报告,通过这个报告,我们就可以了解一个系统的整个运行情况,这就像一个人全面的体 ...

  5. Android 异步开发之 AsyncQueryHandler 批量添加联系人

    AsyncQueryHandler: 官方解释是一个异步帮助类(A helper class to help make handling asynchronous ContentResolver qu ...

  6. iOS 第三方库、插件、知名博客总结

    iOS 第三方库.插件.知名博客总结 用到的组件 1.通过CocoaPods安装 项目名称 项目信息 AFNetworking 网络请求组件 FMDB 本地数据库组件 SDWebImage 多个缩略图 ...

  7. Vue 源码分析——构造函数原型

    在执行 npm run dev 的时候 根据script/config.js 文件中的配置 'web-full-dev': { entry: resolve('web/entry-runtime-wi ...

  8. javascript 中x++和++x的不同

    x++和++x都是给x加一,但是前者是完成赋值之后再递增x,后者相反. 例如:如果x是5,y=x++会将y设置为5,x设置为6:而y=++x会将x和y都设置为6.

  9. VmWare入门指南

    记得以前有大佬曾教过我们用win10的自带双系统运行Ubuntu,但这玩意儿好像玩起来并不简单(反正本人试了一上午也没成功),而且这个系统是和windows交互的,我们也很难调整性能参数.今天,我来教 ...

  10. JavaWeb日常笔记

    1.   XML文档的作用和解析 1. XML的基本概述: XML的主要是用来存储一对多的数据,另外还可以用来当做配置文件存储数据.XML的表头如下: <?xml version='1.0' e ...