[Usaco2009 Jan]安全路经Travel BZOJ1576 Dijkstra+树链剖分+线段树
分析:
Dijkstra求最短路树,在最短路树上进行操作,详情可见上一篇博客:http://www.cnblogs.com/Winniechen/p/9042937.html
我觉得这个东西不压行写出了有点丑...之后写了一个压行后更丑的...
附上压行后的代码:
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
#define N 200005
#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<<2],e[N<<1];
int head[N],head1[N],cnt,cnt1,fa[N],a[N];
int dep[N],anc[N],siz[N],son[N],idx[N],b[N];
int dis[N],minn[N<<2],cov[N<<2],n,vis[N],c[N];
void add1(int x,int y,int z){E[cnt1].to=y;E[cnt1].next=head1[x];E[cnt1].val=z;head1[x]=cnt1++;}
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 Dijkstra()
{
memset(dis,0x3f,sizeof(dis));int num=0;
priority_queue<pair<int ,int > >q;dis[1]=0;q.push(make_pair(0,1));
while(!q.empty())
{
if(num==n)break;
int x=q.top().second;q.pop();
if(vis[x])continue;vis[x]=1;num++;
for(int i=head1[x];i!=-1;i=E[i].next)
{
int to1=E[i].to;
if(dis[to1]+E[i].val==dis[x])add(to1,x,E[i].val),add(x,to1,E[i].val);
}
for(int i=head1[x];i!=-1;i=E[i].next)
{
int to1=E[i].to;
if(dis[x]+E[i].val<dis[to1])
{
dis[to1]=dis[x]+E[i].val;
q.push(make_pair(-dis[to1],to1));
}
}
}
}
void dfs1(int x,int from)
{
fa[x]=from,dep[x]=dep[from]+1,siz[x]=1;
for(int i=head[x];i!=-1;i=e[i].next)
{
int to1=e[i].to;
if(to1!=from)
{
dfs1(to1,x);siz[x]+=siz[to1];
if(siz[son[x]]<siz[to1])son[x]=to1;
}
}
}
int tims;
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 PushDown(int rt)
{
if(cov[rt]!=inf)
{
int t=cov[rt];
cov[rt<<1]=min(cov[rt<<1],t);
minn[rt<<1]=min(minn[rt<<1],t);
cov[rt<<1|1]=min(cov[rt<<1|1],t);
minn[rt<<1|1]=min(minn[rt<<1|1],t);
cov[rt]=inf;
}
}
void build(int l,int r,int rt)
{
minn[rt]=cov[rt]=inf;
if(l==r)return ;int m=(l+r)>>1;
build(lson);build(rson);
}
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(L<=m)Update(L,R,c,lson);
if(m<R)Update(L,R,c,rson);
}
int query(int x,int l,int r,int rt)
{
if(l==r)return minn[rt];
PushDown(rt);int m=(l+r)>>1;
if(m>=x)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 main()
{
int m;memset(head,-1,sizeof(head));memset(head1,-1,sizeof(head1));scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,z;scanf("%d%d%d",&x,&y,&z);
add1(x,y,z);add1(y,x,z);a[i]=x,b[i]=y,c[i]=z;
}
Dijkstra();dfs1(1,0);dfs2(1,1);build(1,n,1);
for(int i=1;i<=m;i++)
{
if(abs(dis[a[i]]-dis[b[i]])==c[i])continue;
get_lca(a[i],b[i],dis[a[i]]+dis[b[i]]+c[i]);
}
for(int i=2;i<=n;i++)
{
int t=query(idx[i],1,n,1);
t==inf?printf("-1\n"):printf("%d\n",t-dis[i]);
}
return 0;
}
[Usaco2009 Jan]安全路经Travel BZOJ1576 Dijkstra+树链剖分+线段树的更多相关文章
- 【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 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
随机推荐
- 深入浅出JWT(JSON Web Token )
1. JWT 介绍 JSON Web Token(JWT)是一个开放式标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间以JSON对象安全传输信息. 这些信息可以通过数字签名进行 ...
- Linux部署集群.NET网站
一.Linux下面安装需要软件 我们这里需要安装的软件有: 1) Mono 3.2.8 : C#跨平台编译器,能使.Net运行与Linux下,目前.net 4.0可以完美运行在该平台下 2) ngin ...
- 从前端开发看HTTP协议的应用
一.Chrome Developer Network Tab Cheome Developer作为现在前端开发者最常用的开发调试工具,其具有前端可以涉及到的各方面的强大功能,为我们的开发和定位问题提供 ...
- The 4 Essentials of Video Content Marketing Success
https://www.entrepreneur.com/article/243208 As videos become increasingly popular, they provide the ...
- Django REST framework+Vue 打造生鲜超市(十三)
目录 生鲜超市(一) 生鲜超市(二) 生鲜超市(三) 生鲜超市(四) 生鲜超市(五) 生鲜超市(六) 生鲜超市(七) 生鲜超市(八) 生鲜超市(九) 生鲜超市(十) ...
- mysql的SQL_NO_CACHE(在查询时不使用缓存)和sql_cache用法
转自:http://www.169it.com/article/5994930453423417575.html 为了测试sql语句的效率,有时候要不用缓存来查询. 使用 SELECT SQL_NO_ ...
- Window 下mysql binlog开启及查看,mysqlbinlog
查看是否开启了binlog: win+r => cmd => 连接mysql=>show variables like 'log_%'; mysql> show variabl ...
- sql中having、group by用法及常用聚合函数
having是用在聚合函数的用法.当我们在用聚合函数的时候,一般都要用到GROUP BY 先进行分组,然后再进行聚合函数的运算.运算完后就要用到HAVING 的用法了,就是进行判断了. 注意:sele ...
- explicit的作用
用来修饰类的构造函数,被修饰的构造函数的类,不能发生相应的隐式类型转换,只能以显示的方式进行类型转换,例如:不加:Circle A = Circle(1.23) 加上之后:只能写:Circle A(1 ...
- select case when与IF的用法
case when概述 sql语句中的case语句与高级语言中的switch语句,是标准sql的语法,适用于一个条件判断有多种值的情况下分别执行不同的操作. case when示例 有一张表,里面有3 ...