最短路 BZOJ3694 樹鏈剖分+線段樹
阿新 • • 發佈:2018-05-16
OS 情況 ostream 最小值 down from == spa sizeof
分析:
樹剖裸題,[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 樹鏈剖分+線段樹