首先用Dijkstra做出最短路生成树,设dis[p]为1到p点的最短路长度

对于一条不在生成树上的边u -> v,不妨设fa为u、v的lca

则一fa到v的路径上的任意点x都可以由u达到,走的方式是1 -> fa -> u -> v -> x,dis'[x] = dis[u] + dis(u, v) + dis[v] - dis[x]

于是可以用dis[u] + dis(u, v) + dis[v]更新fa到v的路径上的所有点

链剖一下,线段树lazytag就好了,连pushdown都不需要

 /**************************************************************
Problem: 1576
User: rausen
Language: C++
Result: Accepted
Time:2276 ms
Memory:16636 kb
****************************************************************/ #include <cstdio>
#include <algorithm>
#include <queue> using namespace std;
const int N = 1e5 + ;
const int M = 2e5 + ;
const int inf = 1e9; struct edge {
int next, to, v, vis;
edge(int _n = , int _t = , int _v = , int __v = ) : next(_n), to(_t), v(_v), vis(__v) {}
} e[M << ]; struct heap_node {
int v, e, to;
heap_node(int _v = , int _e = , int _t = ) : v(_v), e(_e), to(_t) {} inline bool operator < (const heap_node &p) const {
return v > p.v;
}
}; struct tree_node {
int fa, sz, dep;
int top, son, e;
int w;
} tr[N]; struct seg_node {
seg_node *ls, *rs;
int mn;
} *seg_root, *seg_null, mempool[N << ], *cnt_seg = mempool; int n, m, cnt_q;
int first[N], tot = ;
int dis[N];
priority_queue <heap_node> h; inline int read() {
static int x;
static char ch;
x = , ch = getchar();
while (ch < '' || '' < ch)
ch = getchar();
while ('' <= ch && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
return x;
} inline void Add_Edges(int x, int y, int v) {
e[++tot] = edge(first[x], y, v), first[x] = tot;
e[++tot] = edge(first[y], x, v), first[y] = tot;
} inline void add_to_heap(int p) {
static int x;
for (x = first[p]; x; x = e[x].next)
if (dis[e[x].to] == inf)
h.push(heap_node(e[x].v + dis[p], x, e[x].to));
} void Dijkstra(int S) {
int p;
for (p = ; p <= n; ++p) dis[p] = inf;
while (!h.empty()) h.pop();
dis[S] = , add_to_heap(S);
while (!h.empty()) {
if (dis[h.top().to] != inf) {
h.pop();
continue;
}
p = h.top().to;
dis[p] = h.top().v, e[tr[p].e = h.top().e].vis = ;
h.pop(), add_to_heap(p);
}
} #define y e[x].to
#define Son tr[p].son
void dfs(int p) {
int x;
tr[p].sz = ;
for (x = first[p]; x; x = e[x].next)
if (tr[y].e == x) {
tr[y].dep = tr[p].dep + ;
dfs(y);
tr[p].sz += tr[y].sz;
if (Son == || tr[y].sz > tr[Son].sz) Son = y;
}
} void DFS(int p) {
int x;
tr[p].w = ++cnt_q;
if (Son)
tr[Son].top = tr[p].top, DFS(Son);
for (x = first[p]; x; x = e[x].next)
if (y != Son && tr[y].e == x)
tr[y].top = y, DFS(y);
}
#undef y
#undef Son #define mid (l + r >> 1)
#define Ls p -> ls
#define Rs p -> rs
#define Mn p -> mn
inline void seg_make_null(seg_node *&p) {
p = cnt_seg, Ls = Rs = p, Mn = inf;
} inline void seg_new(seg_node *&p) {
p = ++cnt_seg, *p = *seg_null;
} void seg_build(seg_node *&p, int l, int r) {
seg_new(p);
if (l == r) return;
seg_build(Ls, l, mid), seg_build(Rs, mid + , r);
} void seg_modify(seg_node *p, int l, int r, int L, int R, int v) {
if (L <= l && r <= R) {
Mn = min(Mn, v);
return;
}
if (L <= mid) seg_modify(Ls, l, mid, L, R, v);
if (mid + <= R) seg_modify(Rs, mid + , r, L, R, v);
} int seg_query(seg_node *p, int l, int r, int pos) {
if (l == r) return Mn;
return min(Mn, pos <= mid ? seg_query(Ls, l, mid, pos) : seg_query(Rs, mid + , r, pos));
}
#undef mid
#undef Ls
#undef Rs
#undef Mn int get_lca(int x, int y) {
while (tr[x].top != tr[y].top) {
if (tr[tr[x].top].dep < tr[tr[y].top].dep) swap(x, y);
x = tr[tr[x].top].fa;
}
if (tr[x].dep < tr[y].dep) swap(x, y);
return y;
} void work_modify(int x, int fa, int v) {
while (tr[x].top != tr[fa].top) {
seg_modify(seg_root, , n, tr[tr[x].top].w, tr[x].w, v);
x = tr[tr[x].top].fa;
}
seg_modify(seg_root, , n, tr[fa].w + , tr[x].w, v);
} int main() {
int i, x, y, z, fa, tmp;
n = read(), m = read();
for (i = ; i <= m; ++i) {
x = read(), y = read(), z = read();
Add_Edges(x, y, z);
}
Dijkstra();
for (i = ; i <= n; ++i)
tr[i].fa = e[tr[i].e ^ ].to;
dfs();
tr[].top = , DFS();
seg_make_null(seg_null);
seg_build(seg_root, , n);
#define y e[x].to
for (i = ; i <= n; ++i)
for (x = first[i]; x; x = e[x].next)
if (!e[x].vis) work_modify(y, get_lca(i, y), dis[i] + dis[y] + e[x].v);
#undef y
for (i = ; i <= n; ++i) {
tmp = seg_query(seg_root, , n, tr[i].w);
printf("%d\n", tmp == inf ? - : tmp - dis[i]);
}
return ;
}

BZOJ1576 [Usaco2009 Jan]安全路经Travel的更多相关文章

  1. 【思维题 并查集 图论】bzoj1576: [Usaco2009 Jan]安全路经Travel

    有趣的思考题 Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i Output * 第1..N-1行: 第 ...

  2. BZOJ1576: [Usaco2009 Jan]安全路经Travel(树链剖分)

    Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i Output * 第1..N-1行: 第i行包含一个数 ...

  3. BZOJ1576: [Usaco2009 Jan]安全路经Travel(最短路 并查集)

    题意 给你一张无向图,保证从1号点到每个点的最短路唯一.对于每个点求出删掉号点到它的最短路上的最后一条边(就是这条路径上与他自己相连的那条边)后1号点到它的最短路的长度 Sol emmm,考场上想了个 ...

  4. [BZOJ1576] [Usaco2009 Jan]安全路经Travel(堆优化dijk + (并查集 || 树剖))

    传送门 蒟蒻我原本还想着跑两边spfa,发现不行,就gg了. 首先这道题卡spfa,所以需要用堆优化的dijkstra求出最短路径 因为题目中说了,保证最短路径有且只有一条,所以可以通过dfs求出最短 ...

  5. 【BZOJ1576】[Usaco2009 Jan]安全路经Travel 最短路+并查集

    [BZOJ1576][Usaco2009 Jan]安全路经Travel Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, ...

  6. bzoj 1576: [Usaco2009 Jan]安全路经Travel 树链剖分

    1576: [Usaco2009 Jan]安全路经Travel Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 665  Solved: 227[Sub ...

  7. [Usaco2009 Jan]安全路经Travel BZOJ1576 Dijkstra+树链剖分+线段树

    分析: Dijkstra求最短路树,在最短路树上进行操作,详情可见上一篇博客:http://www.cnblogs.com/Winniechen/p/9042937.html 我觉得这个东西不压行写出 ...

  8. bzoj 1576 [Usaco2009 Jan]安全路经Travel(树链剖分,线段树)

    [题意] 给定一个无向图,找到1-i所有的次短路经,要求与最短路径的最后一条边不重叠. [思路] 首先用dijkstra算法构造以1为根的最短路树. 将一条无向边看作两条有向边,考察一条不在最短路树上 ...

  9. bzoj 1576: [Usaco2009 Jan]安全路经Travel——并查集+dijkstra

    Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i Output * 第1..N-1行: 第i行包含一个数 ...

随机推荐

  1. 线程入门之优先级priority

    package com.thread; /** * 优先级: * Thread.MAX_PRIORITY:最大优先级 10 * Thread.MIN_PRIORITY:最小优先级 1 * Thread ...

  2. python_way day19 HTML-day5 (form表单验证,CSRF,cookie,session,缓存)

    python-way day19 1. dJango的form表单验证 2.CSRF 跨站请求伪造 3.cookie,session 4.缓存 一,django表单验证功能 1.django验证基础: ...

  3. 个人博客Week3

    必应软件客户端测评 话不多说 先来一张高大上的客户端界面截图! 首先 映入眼帘的就是四个主要的模块!(1)词典(2)例句(3)翻译(4)应用 (1)词典: 在查询词条的时候,一旦查询了一个词条就不能够 ...

  4. [转载] google mock cookbook

    原文: https://code.google.com/p/googlemock/wiki/CookBook Creating Mock Classes Mocking Private or Prot ...

  5. hdu4588Count The Carries

    链接 去年南京邀请赛的水题,当时找规律过的,看它长得很像数位dp,试了试用数位dp能不能过,d出每位上有多少个1,然后TLE了..然后用规律优化了前4位,勉强过了. 附数位dp代码及找规律代码. #i ...

  6. Android activity之间传值关键性代码

    从当前activity中获取et 表单中的值,并跳转到myactivity.java所绑定的xml布局文件上. private EditText et; Intent intent=new Inten ...

  7. Python学习笔记6-字典

    定义 使用键值对, >>> person = {"name":"keven","age":15,"gender& ...

  8. Java可变参数 & Python可变参数 & Scala可变参数

    Java 可变参数的特点: (1).只能出现在参数列表的最后: (2)....位于变量类型和变量名之间,前后有无空格都可以: (3).调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体 ...

  9. 转:如何学习SQL(第二部分:从关系角度理解SQL)

    转自:http://blog.163.com/mig3719@126/blog/static/285720652010950825538/ 6. 从关系角度理解SQL 6.1. 关系和表 众所周知,我 ...

  10. 使用git命令提交远程github仓库的时候提示"rejected"(拒绝)解决办法

    今天使用在自己笔记本本地磁盘上使用Git命令行执行"git push"然后输入github的用户名和密码之后,报如下错误: ![rejected] master->maste ...