1576: [Usaco2009 Jan]安全路经Travel 最短路径树+树链剖分+线段树
来源:互联网 发布:四ill农信网络学校 编辑:程序博客网 时间:2024/06/03 07:15
神题Orz。
我们可以先dijkstra求出最短路径树。然后有一些不在树上的边,加入后一定会形成一个环,那么此时就为一些点提供了次短路径。
假设我们加入了一条边(u,v),令t=lca(u,v),对于在链t->v上的点x,我们可以走这样一条路线:1->t->u->v->x,画个图可以发现,此时的长度为dis[u]+len(u,v)+dis[v]-dis[x]。dix[x]是已知的,要使结果最小,我们就要使dis[u]+len(u,v)+dis[v]最小。
然后我们可以用树链剖分和线段树来维护一下这个最小值。
#include<iostream>#include<cstdio>#define inf 1000000007#define N 100005using namespace std;int n,m,cnt,sz,dfn;int head[N],dis[N],from[N],belong[N],deep[N],size[N],id[N],fa[N][20];int u[N<<1],v[N<<1],w[N<<1];bool vis[N],mark[N<<2];int next[N<<2],list[N<<2],key[N<<2],tag[N<<2],l[N<<2],r[N<<2];struct node {int v,id;} heap[N];inline int read(){ int a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f;}inline void insert(int x,int y,int z){ next[++cnt]=head[x]; head[x]=cnt; list[cnt]=y; key[cnt]=z;}inline void push(node x){ heap[++sz]=x; int now=sz; while (now&&heap[now].v<heap[now>>1].v) { swap(heap[now],heap[now>>1]); now>>=1; }}inline void pop(){ heap[1]=heap[sz--]; int now=1; while (now<=(sz>>1)) { int next=now<<1; if (next<sz&&heap[next].v>heap[next+1].v) next++; if (heap[now].v<heap[next].v) return; swap(heap[now],heap[next]); now=next; }}inline void dijkstra(){ for (int i=1;i<=n;i++) dis[i]=inf; dis[1]=0; push((node){0,1}); while (sz) { int x=heap[1].id; pop(); if (vis[x]) continue; vis[x]=1; for (int i=head[x];i;i=next[i]) if (dis[list[i]]>dis[x]+key[i]) { dis[list[i]]=dis[x]+key[i]; mark[from[list[i]]]=0; from[list[i]]=i; mark[i]=1; push((node){dis[list[i]],list[i]}); } }}void dfs1(int x){ for (int i=1;(1<<i)<=deep[x];i++) fa[x][i]=fa[fa[x][i-1]][i-1]; size[x]=1; for (int i=head[x];i;i=next[i]) if (mark[i]) { fa[list[i]][0]=x; deep[list[i]]=deep[x]+1; dfs1(list[i]); size[x]+=size[list[i]]; }}void dfs2(int x,int chain){ id[x]=++dfn; belong[x]=chain; int k=0; for (int i=head[x];i;i=next[i]) if (mark[i]&&size[list[i]]>size[k]) k=list[i]; if (!k) return; dfs2(k,chain); for (int i=head[x];i;i=next[i]) if (mark[i]&&list[i]!=k) dfs2(list[i],list[i]);}inline int lca(int x,int y){ if (deep[x]<deep[y]) swap(x,y); int t=deep[x]-deep[y]; for (int i=0;(1<<i)<=t;i++) if ((1<<i)&t) x=fa[x][i]; for (int i=19;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return x==y?x:fa[x][0];}void build(int k,int x,int y){ l[k]=x; r[k]=y; tag[k]=inf; if (l[k]==r[k]) return; int mid=l[k]+r[k]>>1; build(k<<1,x,mid); build(k<<1|1,mid+1,y);}inline void pushdown(int k){ if (l[k]==r[k]|tag[k]==inf) return; tag[k<<1]=min(tag[k<<1],tag[k]); tag[k<<1|1]=min(tag[k<<1|1],tag[k]); tag[k]=inf;}void change(int k,int x,int y,int v){ pushdown(k); if (x==l[k]&&r[k]==y) { tag[k]=min(tag[k],v); return; } int mid=l[k]+r[k]>>1; if (y<=mid) change(k<<1,x,y,v); else if (x>mid) change(k<<1|1,x,y,v); else change(k<<1,x,mid,v),change(k<<1|1,mid+1,y,v);}inline void solve_change(int x,int f,int v){ while (belong[x]!=belong[f]) { change(1,id[belong[x]],id[x],v); x=fa[belong[x]][0]; } if (x!=f) change(1,id[f]+1,id[x],v);}int query(int k,int x){ pushdown(k); if (l[k]==r[k]) return tag[k]; int mid=l[k]+r[k]>>1; if (x<=mid) return query(k<<1,x); else return query(k<<1|1,x);}int main(){ n=read(); m=read(); for (int i=1;i<=m;i++) u[i]=read(),v[i]=read(),w[i]=read(),insert(u[i],v[i],w[i]),insert(v[i],u[i],w[i]); dijkstra(); dfs1(1); dfs2(1,1); build(1,1,n); for (int i=1;i<=m;i++) { int t=lca(u[i],v[i]); if (!mark[2*i-1]) solve_change(v[i],t,dis[u[i]]+dis[v[i]]+w[i]); if (!mark[2*i]) solve_change(u[i],t,dis[u[i]]+dis[v[i]]+w[i]); } for (int i=2;i<=n;i++) { int t=query(1,id[i]); if (t==inf) puts("-1"); else printf("%d\n",t-dis[i]); } return 0;}
0 0
- 1576: [Usaco2009 Jan]安全路经Travel 最短路径树+树链剖分+线段树
- 【最短路径树+可并堆/树链剖分】BZOJ1576 [Usaco2009 Jan]安全路经Travel
- 【BZOJ1576】[Usaco2009 Jan]安全路经Travel【最短路树】【树链剖分】【线段树】
- BZOJ 1576: [Usaco2009 Jan]安全路经Travel【最短路树】【树链剖分】
- [Usaco2009 Jan]安全路经Travel(最短路树+并查集/树链剖分)
- 【BZOJ 1576】 [Usaco2009 Jan]安全路经Travel
- bzoj 1576 [Usaco2009 Jan]安全路经Travel
- bzoj 1576[Usaco2009 Jan]安全路经Travel
- 1576: [Usaco2009 Jan]安全路经Travel
- 【bzoj1576】[Usaco2009 Jan]安全路经Travel
- BZOJ1576: [Usaco2009 Jan]安全路经Travel
- [bzoj1576] [Usaco2009 Jan]安全路经Travel
- [BZOJ1576] [Usaco2009 Jan]安全路经Travel
- [Usaco2009 Jan]安全路经Travel dijkstra + 并查集
- BZOJ1576——[Usaco2009 Jan]安全路经Travel
- BZOJ1576 洛谷P2934 : [Usaco2009 Jan]安全路经Travel
- bzoj 1576: [Usaco2009 Jan]安全路经Travel(dijkstra堆优化+并查集)
- [删边最短路 并查集] BZOJ 1576 [Usaco2009 Jan]安全路经Travel
- 根据对象之间的关系来操作数据
- 对一道面试题的总结与扩展思考(关于一笔画问题的数学分析)
- Oracle 11G在用EXP 导出时,空表不能导出解决
- 禁用或启用戴尔笔记本电脑上的触摸板
- 我与inux系统-开编
- 1576: [Usaco2009 Jan]安全路经Travel 最短路径树+树链剖分+线段树
- 2016 - 我的读书计划
- libc++abi.dylib: terminate_handler unexpectedly threw an exception错误
- 哈希(Hash)与加密(Encrypt)的基本原理、区别及工程应用
- iOS知识点(3)
- Prim最小生成树算法详解以及java实现源代码
- 免费动态域名解析
- 算法杂货铺——分类算法之朴素贝叶斯分类(Naive Bayesian classification)
- C++ Primer Plus (第六版) 编程练习4.13