题意:给定一张图,保证 $1$ 号点到其他所有点的最短路径是唯一的,求:对于点 $i$,不经过 $1$ 到 $i$ 最短路径上最后一条边的最短路.

题解:可以先建出最短路树,然后枚举每一条非树边.

对于一条非树边,影响的只是 $(u,lca)$,$(lca,v)$ 这些点的答案,然后你发现可以写成 $dep[a]-dep[u]+val[i]+dep[v]$

对于 $a$ 来说,第一项是固定的,后面的几项对于一个链来说都是相同的,所以直接用 $LCT$ 维护区间最小值就行了.

#include <bits/stdc++.h>
#define N 100003
#define M 200005
#define ll long long
#define inf 1000000000000
#define inf2 10000000000
#define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout)
using namespace std;
ll output[N];
vector<int>G[N];
int lst[N],from[N],n,m;
namespace Dij
{
ll val[M<<1],d[N];
int hd[N],to[M<<1],nex[M<<1],done[N],edges,s;
struct Node
{
int u;
ll dis;
Node(int u=0,ll dis=0):u(u),dis(dis){}
bool operator<(Node b) const { return b.dis<dis; }
};
priority_queue<Node>q;
void addedge(int u,int v,ll c)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;
}
void dijkstra()
{
memset(d,0x3f,sizeof(d));
d[s]=0ll;
q.push(Node(s,0ll));
while(!q.empty())
{
Node e=q.top(); q.pop();
int u=e.u;
if(done[u]) continue;
done[u]=1;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(d[u]+val[i]<d[v])
{
lst[v]=i;
from[v]=u;
d[v]=d[u]+val[i];
q.push(Node(v, d[v]));
}
}
}
for(int i=2;i<=n;++i) G[from[i]].push_back(i);
}
}
namespace tree
{
int tim;
int size[N],dfn[N],top[N],dep[N],son[N],fa[N];
void dfs1(int u,int ff)
{
fa[u]=ff,size[u]=1,dep[u]=dep[ff]+1;
for(int i=0;i<G[u].size();++i)
{
dfs1(G[u][i],u);
size[u]+=size[G[u][i]];
if(size[G[u][i]]>size[son[u]]) son[u]=G[u][i];
}
}
void dfs2(int u,int tp)
{
top[u]=tp;
if(son[u]) dfs2(son[u], tp);
for(int i=0;i<G[u].size();++i)
if(G[u][i]!=son[u]) dfs2(G[u][i], G[u][i]);
}
int LCA(int x,int y)
{
while(top[x]!=top[y])
{
dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
}
return dep[x]<dep[y]?x:y;
}
};
struct Link_Cut_Tree
{
#define lson p[x].ch[0]
#define rson p[x].ch[1]
int sta[N];
struct Node
{
int ch[2],tag,f,rev;
ll minn,pu,val;
}p[N];
inline int get(int x) { return p[p[x].f].ch[1]==x; }
inline int isrt(int x) { return !(p[p[x].f].ch[0]==x||p[p[x].f].ch[1]==x); }
inline void pushup(int x)
{
p[x].minn=p[x].val;
if(lson) p[x].minn=min(p[x].minn, p[lson].minn);
if(rson) p[x].minn=min(p[x].minn, p[rson].minn);
}
void markrev(int x)
{
if(x) swap(lson,rson), p[x].rev^=1;
}
void marktag(int x,ll v)
{
if(x)
{
p[x].val=min(p[x].val,v);
if(!p[x].tag || p[x].pu>v) p[x].pu=v, p[x].tag=1;
pushup(x);
}
}
void pushdown(int x)
{
if(!x) return;
if(p[x].tag)
{
if(lson) marktag(lson, p[x].pu);
if(rson) marktag(rson, p[x].pu);
p[x].tag=0;
}
if(p[x].rev)
{
if(lson) markrev(lson);
if(rson) markrev(rson);
p[x].rev=0;
}
}
inline void rotate(int x)
{
int old=p[x].f, fold=p[old].f, which=get(x);
if(!isrt(old)) p[fold].ch[p[fold].ch[1]==old]=x;
p[old].ch[which]=p[x].ch[which^1], p[p[old].ch[which]].f=old;
p[x].ch[which^1]=old, p[old].f=x, p[x].f=fold;
pushup(old), pushup(x);
}
inline void splay(int x)
{
int u=x,v=0,fa;
for(sta[++v]=u; !isrt(u); u=p[u].f) sta[++v]=p[u].f;
for(;v;--v) pushdown(sta[v]);
for(u=p[u].f;(fa=p[x].f)!=u;rotate(x))
if(p[fa].f!=u)
rotate(get(fa)==get(x)?fa:x);
}
void Access(int x)
{
for(int y=0;x;y=x,x=p[x].f)
splay(x), rson=y, pushup(x);
}
void makeroot(int x)
{
Access(x), splay(x), markrev(x);
}
void split(int x,int y)
{
makeroot(x), Access(y), splay(y);
}
int find(int x)
{
for(pushdown(x); rson ; pushdown(x))
{
x=rson;
}
return x;
}
#undef lson
#undef rson
}lct;
void build_tree(int u,int ff)
{
lct.p[u].f=ff;
lct.p[u].val=inf;
lct.pushup(u);
for(int i=0;i<G[u].size();++i) build_tree(G[u][i], u);
}
int main()
{
// setIO("input");
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=m;++i)
{
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
Dij::addedge(u,v,1ll*c);
Dij::addedge(v,u,1ll*c);
}
Dij::s=1;
Dij::dijkstra();
tree::dfs1(1,0);
tree::dfs2(1,1);
build_tree(1,0);
for(i=1;i<=n;++i)
{
for(j=Dij::hd[i];j;j=Dij::nex[j])
{
int v=Dij::to[j];
if(lst[v]==j) continue;
int lca=tree::LCA(i,v);
lct.split(v,lca);
int pp=lct.find(lct.p[lca].ch[0]);
if(pp)
{
lct.split(v, pp);
lct.marktag(pp, Dij::d[v]+Dij::d[i]+Dij::val[j]);
}
}
}
for(i=2;i<=n;++i)
{
lct.Access(i);
lct.splay(i);
if(lct.p[i].val>=inf2) printf("-1\n");
else printf("%lld\n",lct.p[i].val-Dij::d[i]);
}
return 0;
}

  

BZOJ 1576 树剖+LCT的更多相关文章

  1. CF827D Best Edge Weight[最小生成树+树剖/LCT/(可并堆/set启发式合并+倍增)]

    题意:一张图求每条边边权最多改成多少可以让所有MST都包含这条边. 这题还是要考察Kruskal的贪心过程. 先跑一棵MST出来.然后考虑每条边. 如果他是非树边,要让他Kruskal的时候被选入,必 ...

  2. [Bzoj2243][SDOI2011]染色(线段树&&树剖||LCT)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2243 线段树+树链剖分,在线段树需要每次用lt和rt两个数组记录当前区间的左右边界的颜色 ...

  3. [GXOI/GZOI2019]旧词(树上差分+树剖)

    前置芝士:[LNOI2014]LCA 要是这题放HNOI就好了 原题:\(\sum_{l≤i≤r}dep[LCA(i,z)]\) 这题:\(\sum_{i≤r}dep[LCA(i,z)]^k\) 对于 ...

  4. BZOJ 4817: [Sdoi2017]树点涂色(LCT+树剖+线段树)

    题目描述 Bob有一棵 nn 个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. Bob ...

  5. [BZOJ 1576] [Usaco2009 Jan] 安全路经Travel 【树链剖分】

    题目链接: BZOJ - 1576 题目分析 首先Orz Hzwer的题解. 先使用 dijikstra 求出最短路径树. 那么对于一条不在最短路径树上的边 (u -> v, w) 我们可以先沿 ...

  6. 洛谷P4332 [SHOI2014]三叉神经树(LCT,树剖,二分查找,拓扑排序)

    洛谷题目传送门 你谷无题解于是来补一发 随便百度题解,发现了不少诸如树剖\(log^3\)LCT\(log^2\)的可怕描述...... 于是来想想怎么利用题目的性质,把复杂度降下来. 首先,每个点的 ...

  7. bzoj 3779 重组病毒 —— LCT+树状数组(区间修改+区间查询)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3779 RELEASE操作可以对应LCT的 access,RECENTER则是 makeroo ...

  8. BZOJ2157 旅游 【树剖 或 LCT】

    题目 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径. ...

  9. BZOJ 3626 [LNOI2014]LCA 树剖+(离线+线段树 // 在线+主席树)

    BZOJ 4012 [HNOI2015]开店 的弱化版,离线了,而且没有边权(长度). 两种做法 1 树剖+离线+线段树 这道题求的是一个点zzz与[l,r][l,r][l,r]内所有点的lcalca ...

随机推荐

  1. 二十四、V4L2框架主要结构体分析和虚拟摄像头驱动编写

    一.V4L2框架主要结构体分析 V4L2(video for linux version 2),是内核中视频设备的驱动框架,为上层访问视频设备提供统一接口. V4L2整体框架如下图: 图中主要包括两层 ...

  2. golang的for循环基本语法

  3. AJAX调用案例随笔(个人观看使用)

    <script type="text/javascript"> /*var contextpath = "http://192.168.0.103:8080/ ...

  4. mysql 子句、子查询、连接查询

    一.mysql查询的五种子句 where子句(条件查询):按照“条件表达式”指定的条件进行查询. group by子句(分组):按照“属性名”指定的字段进行分组.group by子句通常和count( ...

  5. GitHub的Fork是什么意思

    GitHub的Fork 是什么意思[转] GitHub Help Simple guide to forks in GitHub and Git GitHub的Fork 是什么意思-N神3-博客园 G ...

  6. fastjson<1.2.47 RCE 漏洞复现

    这两天爆出了 fastjson 的老洞,复现简单记录一下. 首先使用 spark 搭建一个简易的利用 fastjson 解析 json 的 http server. package cn.hackte ...

  7. Vue.js源码全方位深入解析--学习笔记

    模板中的插入变量是如何渲染到DOM上的? initMixin(Vue)->_init->$options-> $mount()当执行该挂载方法时DOM变化 为什么可以通过this访问 ...

  8. UnknownError: session deleted because of page crash from tab crashed

    一.问题 在docker上跑Selenium+ChromeDriver+Chrome无头模式报错: UnknownError: unknown error: session deleted becau ...

  9. 2019杭电多校三 C. Yukikaze and Demons (点分治)

    大意: 给定树, 每个点有一个十进制数位, 求有多少条路径组成的十进制数被$k$整除. 点分治, 可以参考CF715C, 转化为求$10^a x+b\equiv 0(mod\space k)$的$x$ ...

  10. PHP Math常量

    常量名 常量名 常量值 PHP M_E e 2.7182818284590452354 4 M_EULER Euler 常量 0.57721566490153286061 5.2.0 M_LNPI l ...