BZOJ 1576 树剖+LCT
题意:给定一张图,保证 $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的更多相关文章
- CF827D Best Edge Weight[最小生成树+树剖/LCT/(可并堆/set启发式合并+倍增)]
题意:一张图求每条边边权最多改成多少可以让所有MST都包含这条边. 这题还是要考察Kruskal的贪心过程. 先跑一棵MST出来.然后考虑每条边. 如果他是非树边,要让他Kruskal的时候被选入,必 ...
- [Bzoj2243][SDOI2011]染色(线段树&&树剖||LCT)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2243 线段树+树链剖分,在线段树需要每次用lt和rt两个数组记录当前区间的左右边界的颜色 ...
- [GXOI/GZOI2019]旧词(树上差分+树剖)
前置芝士:[LNOI2014]LCA 要是这题放HNOI就好了 原题:\(\sum_{l≤i≤r}dep[LCA(i,z)]\) 这题:\(\sum_{i≤r}dep[LCA(i,z)]^k\) 对于 ...
- BZOJ 4817: [Sdoi2017]树点涂色(LCT+树剖+线段树)
题目描述 Bob有一棵 nn 个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. Bob ...
- [BZOJ 1576] [Usaco2009 Jan] 安全路经Travel 【树链剖分】
题目链接: BZOJ - 1576 题目分析 首先Orz Hzwer的题解. 先使用 dijikstra 求出最短路径树. 那么对于一条不在最短路径树上的边 (u -> v, w) 我们可以先沿 ...
- 洛谷P4332 [SHOI2014]三叉神经树(LCT,树剖,二分查找,拓扑排序)
洛谷题目传送门 你谷无题解于是来补一发 随便百度题解,发现了不少诸如树剖\(log^3\)LCT\(log^2\)的可怕描述...... 于是来想想怎么利用题目的性质,把复杂度降下来. 首先,每个点的 ...
- bzoj 3779 重组病毒 —— LCT+树状数组(区间修改+区间查询)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3779 RELEASE操作可以对应LCT的 access,RECENTER则是 makeroo ...
- BZOJ2157 旅游 【树剖 或 LCT】
题目 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径. ...
- BZOJ 3626 [LNOI2014]LCA 树剖+(离线+线段树 // 在线+主席树)
BZOJ 4012 [HNOI2015]开店 的弱化版,离线了,而且没有边权(长度). 两种做法 1 树剖+离线+线段树 这道题求的是一个点zzz与[l,r][l,r][l,r]内所有点的lcalca ...
随机推荐
- java之aop使用及自定义注解
目的: 1.Java注解简介 2.Java元注解(重点) 3.自定义注解 案例一(获取类与方法上的注解值) 案例二(获取类属性上的注解属性值) 案例三(获取参数修饰注解对应的属性值) 4.Aop自定义 ...
- MySQL 体系结构及存储引擎
MySQL 原理篇 MySQL 索引机制 MySQL 体系结构及存储引擎 MySQL 语句执行过程详解 MySQL 执行计划详解 MySQL InnoDB 缓冲池 MySQL InnoDB 事务 My ...
- 【转载】C#通过IndexOf方法判断某个字符串是否包含在另一个字符串中
C#开发过程中针对字符串String类型的操作是常见操作,有时候需要判断某个字符串是否包含在另一个字符串,此时可以使用IndexOf方法以及Contain方法来实现此功能,Contain方法返回Tru ...
- python day3 int,str,list类型补充
目录 python day 3 1. int类小知识点 2. str类小知识点 3. list类小知识点 python day 3 (学习资料来自老男孩教育) 2019/10/06 1. int类小知 ...
- rem em min-width: 30em 的意思
30em=30rem=30x16px=480px @media only screen and (min-width:30 em){ }
- vue实现组件切换的两种方式
<!DOCTYPE html> <html> <head> <title>组件的切换</title> <meta charset=&q ...
- Vue路由规则中定义参数
Vue使用routerLinke定义参数的时候 路由规则中不需要更改任何属性. 路由其实就是我们在html中定义的锚点,点击这个连接跳转一个锚点.vue中的路由也是这个原理, 前提是路由必须创建在实 ...
- 【异常】Maxwell异常 Exception in thread "main" net.sf.jsqlparser.parser.TokenMgrError: Lexical error at line 1, column 596. Encountered: <EOF> after : ""
1 详细异常 Exception in thread "main" net.sf.jsqlparser.parser.TokenMgrError: Lexical error at ...
- 001——搭建OpenCV实验环境
开发环境 VS 2017 15.7.6 OpenCV 3.4.1 搭建环境 设置环境变量 创建Win32 空项目 配置属性管理器 测试代码 #include<opencv2/opencv.hpp ...
- Python使用xlrd、pandas包从Excel读取数据
#coding=utf-8 # pip install xlrd import xlrd def read_from_xls(filepath,index_col_list): #filepath:读 ...