【FJOI2014】最短路径树问题
题面
题解
强行将最短路和点分治(长链剖分)融合在一起的题目
构建出字典序最小的最短路树之后,就可以用点分治来解决了
不过有一些细节要注意:
3 3 k
1 2 1
2 3 1
1 3 2
这样建出的最短路树是\(1-2-3\)
而不是\(1-2,1-3\)
相信这组美妙的数据可以帮助你调错
这组\(hack\)数据的核心和上面那个是一样的
代码
#include<cstdio>
#include<cstring>
#include<cctype>
#include<climits>
#include<algorithm>
#include<queue>
#define RG register
#define clear(x, y) memset(x, y, sizeof(x))
inline int read()
{
int data = 0, w = 1; char ch = getchar();
while(ch != '-' && (!isdigit(ch))) ch = getchar();
if(ch == '-') w = -1, ch = getchar();
while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
return data * w;
}
const int maxn(30010);
int n, m, K;
struct edge { int next, to, dis; };
inline void add_edge(int, int, int);
namespace Dij
{
std::vector<std::pair<int, int> > g[maxn]; bool vis[maxn];
int dis[maxn];
inline void add_edge(int from, int to, int dis)
{
g[from].push_back(std::make_pair(to, dis));
g[to].push_back(std::make_pair(from, dis));
}
std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int> >,
std::greater<std::pair<int, int> > > Q;
void dfs(int x)
{
vis[x] = 1;
for(std::vector<std::pair<int, int> >::iterator
i = g[x].begin(); i != g[x].end(); ++i)
{
int to = i -> first; if(vis[to]) continue;
if(dis[to] == dis[x] + i -> second)
::add_edge(x, to, i -> second), dfs(to);
}
}
void main()
{
for(RG int i = 1; i <= n; i++) std::sort(g[i].begin(), g[i].end());
for(RG int i = 1; i <= n; i++) dis[i] = INT_MAX >> 1;
Q.push(std::make_pair(dis[1] = 0, 1));
while(!Q.empty())
{
int x = Q.top().second; Q.pop(); if(vis[x]) continue;
vis[x] = 1;
for(std::vector<std::pair<int, int> >::iterator
i = g[x].begin(); i != g[x].end(); ++i)
{
int to = i -> first; if(vis[to]) continue;
if(dis[x] + i -> second < dis[to])
{
dis[to] = dis[x] + i -> second;
Q.push(std::make_pair(dis[to], to));
}
}
}
clear(vis, 0); dfs(1);
}
}
edge e[maxn << 1]; int head[maxn], e_num;
inline void add_edge(int from, int to, int dis)
{
e[++e_num] = (edge) {head[from], to, dis}; head[from] = e_num;
e[++e_num] = (edge) {head[to], from, dis}; head[to] = e_num;
}
bool vis[maxn];
int SIZE, _min, root, size[maxn], stk[maxn], cnt_tdep[maxn];
int top, tdep[maxn], ans, cnt_ans, dep[maxn];
void GetRoot(int x, int fa)
{
size[x] = 1; int tot = 0;
for(RG int i = head[x]; i; i = e[i].next)
{
int to = e[i].to; if(vis[to] || to == fa) continue;
GetRoot(to, x); size[x] += size[to];
tot = std::max(tot, size[to]);
}
tot = std::max(tot, SIZE - size[x]);
if(tot < _min) _min = tot, root = x;
}
void GetDep(int x, int fa, int _dep, int _dis)
{
stk[++top] = x;
if(tdep[_dep] <= _dis)
{
if(tdep[_dep] == _dis) ++cnt_tdep[_dep];
else tdep[_dep] = _dis, cnt_tdep[_dep] = 1;
}
for(RG int i = head[x]; i; i = e[i].next)
{
int to = e[i].to; if(vis[to] || to == fa) continue;
GetDep(to, x, _dep + 1, _dis + e[i].dis);
}
}
void Calc(int x, int fa, int _dep, int _dis)
{
dep[x] = _dep;
if(dep[x] < K - 1)
{
int nowdis = tdep[K - _dep - 1] + _dis;
if(ans <= nowdis)
{
if(ans == nowdis) cnt_ans += cnt_tdep[K - _dep - 1];
else ans = nowdis, cnt_ans = cnt_tdep[K - _dep - 1];
}
}
for(RG int i = head[x]; i; i = e[i].next)
{
int to = e[i].to; if(vis[to] || to == fa) continue;
Calc(to, x, _dep + 1, _dis + e[i].dis);
}
}
void dfs(int x)
{
vis[x] = 1, top = 0;
for(RG int i = head[x]; i; i = e[i].next)
{
int to = e[i].to; if(vis[to]) continue;
Calc(to, x, 1, e[i].dis), GetDep(to, x, 1, e[i].dis);
}
if(ans <= tdep[K - 1])
{
if(ans == tdep[K - 1]) cnt_ans += cnt_tdep[K - 1];
else ans = tdep[K - 1], cnt_ans = cnt_tdep[K - 1];
}
for(RG int i = 1; i <= top; i++)
cnt_tdep[dep[stk[i]]] = tdep[dep[stk[i]]] = 0;
for(RG int i = head[x]; i; i = e[i].next)
{
int to = e[i].to; if(vis[to]) continue;
SIZE = _min = size[to], root = 0; GetRoot(to, x);
dfs(root);
}
}
int main()
{
n = read(), m = read(), K = read();
for(RG int i = 1, a, b, c; i <= m; i++)
a = read(), b = read(), c = read(),
Dij::add_edge(a, b, c);
Dij::main();
SIZE = _min = n; GetRoot(1, 0); dfs(root);
printf("%d %d\n", ans, cnt_ans);
return 0;
}
【FJOI2014】最短路径树问题的更多相关文章
- [BZOJ4016][FJOI2014]最短路径树问题
[BZOJ4016][FJOI2014]最短路径树问题 试题描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长 ...
- 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出发,往其余所有点分别走一次并返回. 往某一个点走时,选择 ...
- 【BZOJ4016】[FJOI2014]最短路径树问题
[BZOJ4016][FJOI2014]最短路径树问题 题面 bzoj 洛谷 题解 虽然调了蛮久,但是思路还是蛮简单的2333 把最短路径树构出来,然后点分治就好啦 ps:如果树构萎了,这组数据可以卡 ...
- [FJOI2014]最短路径树问题 长链剖分
[FJOI2014]最短路径树问题 LG传送门 B站传送门 长链剖分练手好题. 如果你还不会长链剖分的基本操作,可以看看我的总结. 这题本来出的很没水平,就是dijkstra(反正我是不用SPFA)的 ...
- [BZOJ4016][FJOI2014]最短路径树问题(dijkstra+点分治)
4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 1796 Solved: 625[Submit][Sta ...
- 洛谷 [FJOI2014]最短路径树问题 解题报告
[FJOI2014]最短路径树问题 题目描述 给一个包含\(n\)个点,\(m\)条边的无向连通图.从顶点\(1\)出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多 ...
- 【BZOJ4016】[FJOI2014]最短路径树问题 最短路径树+点分治
[BZOJ4016][FJOI2014]最短路径树问题 Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径 ...
- 【BZOJ4016】[FJOI2014]最短路径树问题(点分治,最短路)
[BZOJ4016][FJOI2014]最短路径树问题(点分治,最短路) 题面 BZOJ 洛谷 题解 首先把最短路径树给构建出来,然后直接点分治就行了. 这个东西似乎也可以长链剖分,然而没有必要. # ...
- bzoj 4016: [FJOI2014]最短路径树问题
bzoj4016 最短路路径问题 Time Limit: 5 Sec Memory Limit: 512 MB Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点 ...
随机推荐
- windows server 2016 无法联网问题
首先,联网分解为两个问题,一.WLAN(无线网).二.以太网(有线网) 一 .WLAN问题解决方案 1.打开服务器管理器 2.添加角色和功能 3.一直点下一步到“功能”,勾选 DirectPlay 和 ...
- October 09th 2017 Week 41st Monday
My motto is: Contended with little, yet wishing for more. 我的座右铭是:为一点点感到满足,但希望获得更多. If you can live y ...
- 第一篇,编译生成libcef_dll_wrapper
因为工作原因需要在程序里面嵌入地图,在网上看了百度地图和高德地图都没有提供c++的接口,提供有web接口,那只好在程序里面嵌入web控件了,第一想到的是web browser控件,接着脑海里又想到IE ...
- css画图那些事
上一篇css3写了一些基本的图形,想到是不是能用css3画个动物,便在网上找图片.于是选中一只大鹏鸟 也不难,一步步的写出身体部位,再定位上去就好了.来一张效果图,后面给两个加了动画,稍微难看一点,后 ...
- 【转载】 socket recv 和 read
转自: http://blog.csdn.net/rankun1/article/details/50488989 send函数工作原理: send函数只负责将数据提交给协议层. 当调用该函数时,se ...
- 缓冲区溢出基础实践(一)——shellcode 与 ret2libc
最近结合软件安全课程上学习的理论知识和网络资料,对缓冲区溢出漏洞的简单原理和利用技巧进行了一定的了解.这里主要记录笔者通过简单的示例程序实现缓冲区溢出漏洞利用的步骤,按由简至繁的顺序,依次描述简单的 ...
- 使用Linux进行缓冲区溢出实验的配置记录
在基础的软件安全实验中,缓冲区溢出是一个基础而又经典的问题.最基本的缓冲区溢出即通过合理的构造输入数据,使得输入数据量超过原始缓冲区的大小,从而覆盖数据输入缓冲区之外的数据,达到诸如修改函数返回地址等 ...
- _viewstart.cshtml的作用
在ASP.NET MVC 3.0及更高版本中,用Razor模板引擎新建项目后,Views目录下会出现一个这样的文件:_ViewStart.cshtml. _viewstart.cshtml的作用 1. ...
- TensorFlow函数(七)tf.argmax()
tf.argmax(input, dimension, name=None) 参数: input:输入数据 dimension:按某维度查找. dimension=0:按列查找: dimension= ...
- Sql Server 数据库扩展
1. 查询一个表的所有列名 ------查询一个表的所有列名 Select Name FROM SysColumns Where id=Object_Id('Sys_User') select t.c ...