最短路 BZOJ3694 树链剖分+线段树
分析:
树剖裸题,[Usaco2009 Jan]安全路经Travel 的简化版
剖开最短路树,遍历每一条没在最短路树上的边。
这种情况下,有且仅有u到v路径上,出来lca之外的点能够通过这条边到达,并且,路径长度为:dis[u]+dis[v]+val-dis[x];(dis[x]是从根到x的最短路长度,x是路径上除了lca之外的点)
那么,我们考虑这种情况下,需要维护出树上最小值,那么可以用到线段树维护。
附上代码:
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
#define N 10005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define inf 0x3f3f3f3f
struct node
{
int to,next,val;
}e[N<<1];
struct no
{
int x,y,z;
}a[200000];
int head[N],cnt,dep[N],dis[N],fa[N],son[N],siz[N],anc[N],idx[N],tims,minn[N<<2],cov[N<<2],n;
void add(int x,int y,int z)
{
e[cnt].to=y;
e[cnt].next=head[x];
e[cnt].val=z;
head[x]=cnt++;
}
void dfs1(int x,int from)
{
fa[x]=from,siz[x]=1,dep[x]=dep[from]+1;
for(int i=head[x];i!=-1;i=e[i].next)
{
int to1=e[i].to;
if(to1!=from)
{
dis[to1]=dis[x]+e[i].val;
dfs1(to1,x);
siz[x]+=siz[to1];
if(siz[son[x]]<siz[to1])son[x]=to1;
}
}
}
void dfs2(int x,int top)
{
anc[x]=top;idx[x]=++tims;
if(son[x])dfs2(son[x],top);
for(int i=head[x];i!=-1;i=e[i].next)
{
int to1=e[i].to;
if(to1!=fa[x]&&to1!=son[x])dfs2(to1,to1);
}
}
void PushUp(int rt)
{
minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
}
void PushDown(int rt)
{
if(cov[rt]!=inf)
{
cov[rt<<1]=min(cov[rt],cov[rt<<1]);
minn[rt<<1]=min(cov[rt],minn[rt<<1]);
cov[rt<<1|1]=min(cov[rt],cov[rt<<1|1]);
minn[rt<<1|1]=min(cov[rt],minn[rt<<1|1]);
cov[rt]=inf;
}
}
void build(int l,int r,int rt)
{
cov[rt]=inf;
if(l==r)
{
minn[rt]=inf;return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void Update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
minn[rt]=min(minn[rt],c);
cov[rt]=min(cov[rt],c);
return ;
}
PushDown(rt);
int m=(l+r)>>1;
if(m>=L)Update(L,R,c,lson);
if(m<R)Update(L,R,c,rson);
PushUp(rt);
}
int query(int x,int l,int r,int rt)
{
if(l==r)return minn[rt];
PushDown(rt);
int m=(l+r)>>1;
if(x<=m)return query(x,lson);
else return query(x,rson);
}
void get_lca(int x,int y,int c)
{
while(anc[x]!=anc[y])
{
if(dep[anc[x]]<dep[anc[y]])swap(x,y);
Update(idx[anc[x]],idx[x],c,1,n,1);
x=fa[anc[x]];
}
if(dep[x]>dep[y])swap(x,y);
if(x!=y)Update(idx[x]+1,idx[y],c,1,n,1);
}
int cnt1;
int main()
{
int m;
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,z,op;
scanf("%d%d%d%d",&x,&y,&z,&op);
if(op)
{
add(x,y,z);
add(y,x,z);
}
else
{
a[++cnt1].x=x;
a[cnt1].y=y;
a[cnt1].z=z;
}
}
dfs1(1,0);
dfs2(1,1);
build(1,n,1);
for(int i=1;i<=cnt1;i++)
{
int x=a[i].x,y=a[i].y,z=a[i].z;
get_lca(x,y,dis[x]+dis[y]+z);
}
for(int i=2;i<=n;i++)
{
int t=query(idx[i],1,n,1);
if(t==inf)printf("-1 ");
else printf("%d ",t-dis[i]);
}
return 0;
}
最短路 BZOJ3694 树链剖分+线段树的更多相关文章
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
随机推荐
- 运行Applet程序
[操作方法1:]① 编辑源程序welcome.java.② 编译程序 javac welcome.java③ 将Applet嵌入HTML网页.方法是,用记事本创建一个文件,文件内容如下:<app ...
- 排序算法的C语言实现(下 线性时间排序:计数排序与基数排序)
计数排序 计数排序是一种高效的线性排序. 它通过计算一个集合中元素出现的次数来确定集合如何排序.不同于插入排序.快速排序等基于元素比较的排序,计数排序是不需要进行元素比较的,而且它的运行效率要比效率为 ...
- win10安装wmi报错问题
在win10上,安装wmi,首先下载https://pypi.python.org/pypi/WMI/#downloads,将wmi下载下来 安装过程中,会报错,No Python installat ...
- C++string函数之strcat_s
跟上一篇的strcpy_s一样,是新推出的较为安全的strcat函数 strcat_s脱胎于strcat,用于两个字符串的链接,strcat(str1,str2)直接返回新的str1. 但在vs200 ...
- java中split分割"."的问题
今天使用split分割"."的时候居然失败了,经过百度发现原来要加转义字符才行. 正确的写法: String test="1.2.3"; String[] s1 ...
- python中元组、列表、字典、集合知识
像列表一样处理字符串: 仅需要看字符串的首字符就知道如何处理该字符串的情况也很常见.例如,如果有一个姓与名的列表,您可以使用与列表相同的语法查看名与姓的第一个字符.这种看待字符串的方法叫做分片(sli ...
- Kali学习笔记4:Wireshark详细使用方法
Kali Linux自带Wireshark工具使用介绍: 1.进入界面 这里Lua脚本报错,无需关注 开始使用: 双击第一个eth0:以太网0,开始抓包: 点击上边的这个按钮可以设置: 这里注意:需要 ...
- 什么是C语言。C语言入门
C语言是一种通用计算机编程语言,应用广泛. C语言的设计目标是提供一种编程语言,它可以编译,处理低级内存,生成少量机器代码,并以简单的方式运行,而无需任何操作环境的支持.虽然C语言提供了许多低级处理功 ...
- 适合Python的5大练手项目, 你练了么?
在练手项目的选择上,还存在疑问?不知道要从哪种项目先下手? 首先有两点建议: 最好不要写太应用的程序练手,要思考什么更像是知识,老只会写写爬虫是无用的,但是完全不写也不行. 对于练手的程序,要注意简化 ...
- mysql 基本命令操作
1. 查看存储引擎 show engines; 2. 查看数据存储位置 show variables like 'datadir': 3. 存储引擎 create table mytest engin ...