最短路 bzoj-3694

题目大意:给你一个n个点m条边的无向图,源点为1,并且以点1为根给出最短路树。求对于2到n的每个点i,求最短路,要求不经过给出的最短路树上的1到i的路径上的最后一条边。

注释:$1\le n \le 4000$,$1\le m\le 10^5$。

想法:对于任意两个点uv,满足u和v之间直接相连了一条不在给出最短路树上的边,我们设这条边的长度为val(u,v)。对于任意的一个点i,它到根节点的最短路,也就是从根节点开始走最短路树所到达i的路径和,我们设为dis[i]。那么,对于u到lca(u,v)之间的任意一个点x,我们都可以从1(root)$\rightarrow$t$\rightarrow$v$\rightarrow$u$\rightarrow$x。我们可以用这条路径更新x的答案。这条路径的长度是dis[v]+val(u,v)+dis[u]-dix(x)。我们只需要令这样的(dis[v]+val(u,v)-dis[u])即可。显然,每两个这样满足条件的u和v,都可以更新从u到lca(u,v)之间的点和v到lca(u,v)之间的点,就是区间取min。这个操作我们可以用树链剖分+线段树实现。

最后,附上丑陋的代码... ...

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 1000000000
using namespace std;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,cnt1,cnt2=1,place;
int bin[12];
int u[100005],v[100005],w[100005];
int dis[100005],deep[100005],son[100005],fa[100005][12];
int pl[100005],belong[100005];
struct data{int to,next,v;}e[100005];int head[100005];
struct seg{int l,r,v,tag;}t[400005];
void ins(int u,int v,int w)
{
e[++cnt1].to=v;e[cnt1].next=head[u];head[u]=cnt1;e[cnt1].v=w;
}
void insert(int u,int v,int w)
{
ins(u,v,w);ins(v,u,w);
}
void dfs1(int x,int f)
{
for(int i=1;i<=11;i++)
if(bin[i]<=deep[x])fa[x][i]=fa[fa[x][i-1]][i-1];
else break;
son[x]=1;
for(int i=head[x];i;i=e[i].next)
{
if(e[i].to==f)continue;
deep[e[i].to]=deep[x]+1;
fa[e[i].to][0]=x;
dis[e[i].to]=dis[x]+e[i].v;
dfs1(e[i].to,x);
son[x]+=son[e[i].to];
}
}
void dfs2(int x,int chain)
{
belong[x]=chain;place++;pl[x]=place;
int k=0;
for(int i=head[x];i;i=e[i].next)
if(deep[e[i].to]>deep[x]&&son[e[i].to]>son[k])
k=e[i].to;
if(k)dfs2(k,chain);
for(int i=head[x];i;i=e[i].next)
if(deep[e[i].to]>deep[x]&&e[i].to!=k)
dfs2(e[i].to,e[i].to);
}
int lca(int x,int y)
{
if(deep[x]<deep[y])swap(x,y);
int t=deep[x]-deep[y];
for(int i=0;i<=11;i++)
if(bin[i]&t)x=fa[x][i];
for(int i=11;i>=0;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
if(x==y)return x;
return fa[x][0];
}
void build(int k,int l,int r)
{
t[k].l=l;t[k].r=r;t[k].tag=inf;
if(l==r){t[k].v=inf;return;}
int mid=(l+r)>>1;
build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}
void pushdown(int k)
{
if(t[k].tag==inf||t[k].l==t[k].r)return;
int tag=t[k].tag;t[k].tag=inf;
t[k<<1].tag=min(t[k<<1].tag,tag);
t[k<<1|1].tag=min(t[k<<1|1].tag,tag);
if(t[k<<1].l==t[k<<1].r)t[k<<1].v=min(t[k<<1].v,tag);
if(t[k<<1|1].l==t[k<<1|1].r)t[k<<1|1].v=min(t[k<<1|1].v,tag);
}
void update(int k,int x,int y,int v)
{
pushdown(k);
int l=t[k].l,r=t[k].r;
if(x==l&&y==r)
{
t[k].tag=min(t[k].tag,v);
if(l==r)t[k].v=min(v,t[k].v);
return;
}
int mid=(l+r)>>1;
if(y<=mid)update(k<<1,x,y,v);
else if(x>mid)update(k<<1|1,x,y,v);
else {update(k<<1,x,mid,v);update(k<<1|1,mid+1,y,v);}
}
int ask(int k,int x)
{
pushdown(k);
int l=t[k].l,r=t[k].r;
if(l==r)return t[k].v;
int mid=(l+r)>>1;
if(x<=mid)return ask(k<<1,x);
else return ask(k<<1|1,x);
}
void solveupdate(int x,int f,int v)
{
while(belong[x]!=belong[f])
{
update(1,pl[belong[x]],pl[x],v);
x=fa[belong[x]][0];
}
if(x!=f)update(1,pl[f]+1,pl[x],v);
}
void solve()
{
build(1,1,n);
for(int i=1;i<cnt2;i++)
{
int t=lca(u[i],v[i]);
solveupdate(u[i],t,dis[u[i]]+dis[v[i]]+w[i]);
solveupdate(v[i],t,dis[u[i]]+dis[v[i]]+w[i]);
}
for(int i=2;i<=n;i++)
{
int t=ask(1,pl[i]);
if(t!=inf)printf("%d ",t-dis[i]);
else printf("-1 ");
}
}
int main()
{
//freopen("shortest.in","r",stdin);
//freopen("shortest.out","w",stdout);
bin[0]=1;for(int i=1;i<=12;i++)bin[i]=bin[i-1]*2;
n=read();m=read();
for(int i=1;i<=m;i++)
{
u[cnt2]=read();v[cnt2]=read(),w[cnt2]=read();
bool f=read();
if(!f)cnt2++;
else insert(u[cnt2],v[cnt2],w[cnt2]);
}
dfs1(1,0);dfs2(1,1);
solve();
return 0;
}

小结:考虑一个最值问题我们通常考虑一个式子可以更新什么样的情况下什么样的值,或者什么样的值可以被什么样情况的状态更新。比如说我们在进行倍增floyd时,我们是想到了每一条对于每一条最短路来讲,它的最后一条边可以从那些点来更新,从而想到矩阵来一遍一遍乘。而这个操作可以用矩乘优化。这道题也是同理,我们想到每一个点可以从哪种路径来进行更新,我们想到了如上述的方法,又因为给出的是最短路树,所以根节点到一个点的最短路一定是最短路树上的。更加说明了我们算法的正确性。

[bzoj3694]最短路_树链剖分_线段树的更多相关文章

  1. poj 3237 Tree(树链剖分,线段树)

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 7268   Accepted: 1969 Description ...

  2. 【BZOJ3531】旅行(树链剖分,线段树)

    [BZOJ3531]旅行(树链剖分,线段树) 题面 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教 ...

  3. bzoj 4034 [HAOI2015] T2(树链剖分,线段树)

    4034: [HAOI2015]T2 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1536  Solved: 508[Submit][Status] ...

  4. bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 10677  Solved: 4313[Submit ...

  5. bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1272  Solved: 451[Submit][Status ...

  6. bzoj 2243 [SDOI2011]染色(树链剖分,线段树)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4637  Solved: 1726[Submit][Status ...

  7. HDU 4366 Successor(树链剖分+zkw线段树+扫描线)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4366 [题目大意] 有一个公司,每个员工都有一个上司,所有的人呈树状关系,现在给出每个人的忠诚值和 ...

  8. 【BZOJ5507】[GXOI/GZOI2019]旧词(树链剖分,线段树)

    [BZOJ5507][GXOI/GZOI2019]旧词(树链剖分,线段树) 题面 BZOJ 洛谷 题解 如果\(k=1\)就是链并裸题了... 其实\(k>1\)发现还是可以用类似链并的思想,这 ...

  9. 【洛谷5439】【XR-2】永恒(树链剖分,线段树)

    [洛谷5439][XR-2]永恒(树链剖分,线段树) 题面 洛谷 题解 首先两个点的\(LCP\)就是\(Trie\)树上的\(LCA\)的深度. 考虑一对点的贡献,如果这两个点不具有祖先关系,那么这 ...

  10. BZOJ.4515.[SDOI2016]游戏(树链剖分 李超线段树)

    BZOJ 洛谷 每次在路径上加的数是个一次函数,容易看出是树剖+李超线段树维护函数最小值.所以其实依旧是模板题. 横坐标自然是取个确定的距离标准.取每个点到根节点的距离\(dis[i]\)作为\(i\ ...

随机推荐

  1. Linux 用户管理(1) (/etc/passwd)

    Linux所有的用户都在/etc/passwd文件里面. 1.为什么需要用户 1)计算机及网络资源的合理分配  2)可以控制用户访问系统的权限.3)身份认证 4) 进程 以某个用户的身份来运行 2.用 ...

  2. 详细介绍idea实现javaweb项目登入注册(华东交通大学教务处信息管理系统)、模糊查询

    详细介绍idea实现javaweb项目登入注册(华东交通大学教务处信息管理系统).模糊查询 1,创建数据库,我的用户名:root 密码:root,数据库名称:lianwei,表名:login 2,效果 ...

  3. 51nod1565 FFT

    思路: 显然拆位FFT 不解释 //By SiriusRen #include <bits/stdc++.h> using namespace std; ; ); ,L,S,T,k,sa[ ...

  4. 【POJ3255/洛谷2865】[Usaco2006 Nov]路障Roadblocks(次短路)

    题目: POJ3255 洛谷2865 分析: 这道题第一眼看上去有点懵-- 不过既然要求次短路,那估计跟最短路有点关系,所以就拿着优先队列优化的Dijkstra乱搞,搞着搞着就通了. 开两个数组:\( ...

  5. ACM_三角形蛇形矩阵

    三角形蛇形矩阵 Time Limit: 2000/1000ms (Java/Others) Problem Description: 小铠觉得各类题型是要温故而知新的,所以他叫小发出一道类似做过的题. ...

  6. UNIX环境高级编程--2

    UNIX标准及实现 ISO C: 国际标准化组织(International Organization for standardization , ISO)ISO C标准的意图是提供C程序的可移植性, ...

  7. 关于用友 U8-UAP二开的一些事

    这是关于一个刚刚接触用友U8的二次开发的一些小心得. 首先就是用友二开的论坛,http://u8dev.yonyou.com/ 当然这个论坛做得不怎么样,提出了好几个问题,都没有回复的. 以下是关于二 ...

  8. webSocket客服在线交谈

    一>用户端 <%@ page language="java" pageEncoding="UTF-8" %><%@ taglib uri ...

  9. mac中显示隐藏文件和.开头的文件

    在控制台中执行一下命令,即可在finder中看到此类文件: defaults write com.apple.Finder AppleShowAllFiles YES killall Finder

  10. jQuery怎么去掉标签的hover效果

    今天项目中遇到jquery去掉hover效果的问题,开始以为直接unbind(“hover”)就可以搞定,可是实际验证这个方法并没有作用,正确的使用方法应该是下面这样: /* 这种方法是新增的,在老的 ...