BZOJ 1576 [USACO]安全路经Travel (树剖+线段树)
题目大意:
给你一张无向图,求1到其他节点 不经过最短路的最后一条边 的最短路长度,保证每个节点的最短路走法唯一
神题,$USACO$题目的思维是真的好
先$dijkstra$出最短路树
对于每个节点,符合条件的走法必须满足,不经过它和它父亲之间的连边
显然只能从它的某个子节点走向它,就像绕了一圈
可以证明最优的合法路径一定只经过一条非树边,因为最短路方案唯一
如果还经过另外一条非树边,不论这条边在哪,都肯定会绕远
对于一条非树边$e<x,y>$,它连接了两个节点$x,y$,它们的$lca$是$f$
显然$x$到$f$路径上的某个点$S$(除了$f$点),都存在一条合法路径,从根节点沿树边走到$y$,经过$e<x,y>$走到$x$,再向上沿树边走到$S$
这段路径的长度是$dis_{x}+dis_{y}+dis_{e<x,y>}-dis_{S}$
对于$y$到$f$的路径也是同理
上面的式子可以用线段树+树链剖分序维护
1 #include <queue> 2 #include <vector> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #define N1 1010 7 #define M1 2010 8 #define S1 (N1<<1) 9 #define T1 (N1<<2) 10 #define ll long long 11 #define uint unsigned int 12 #define rint register int 13 #define dd double 14 #define il inline 15 #define inf 233333333 16 using namespace std; 17 18 int gint() 19 { 20 int ret=0,fh=1;char c=getchar(); 21 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 22 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 23 return ret*fh; 24 } 25 int n,m; 26 struct Edge{ 27 int to[M1*2],nxt[M1*2],val[M1*2],head[N1],cte; 28 void ae(int u,int v,int w) 29 {cte++,to[cte]=v,nxt[cte]=head[u],val[cte]=w,head[u]=cte;} 30 }E,T; 31 struct SEG{ 32 int mi[T1]; 33 void pushdown(int rt) 34 { 35 mi[rt<<1]=min(mi[rt<<1],mi[rt]); 36 mi[rt<<1|1]=min(mi[rt<<1|1],mi[rt]); 37 } 38 void build(int l,int r,int rt) 39 { 40 mi[rt]=inf; 41 if(l==r) return; 42 int mid=(l+r)>>1; 43 build(l,mid,rt<<1); 44 build(mid+1,r,rt<<1|1); 45 } 46 void update(int L,int R,int l,int r,int rt,int w) 47 { 48 if(L<=l&&r<=R) {mi[rt]=min(mi[rt],w);return;} 49 int mid=(l+r)>>1; pushdown(rt); 50 if(L<=mid) update(L,R,l,mid,rt<<1,w); 51 if(R>mid) update(L,R,mid+1,r,rt<<1|1,w); 52 } 53 int query(int x,int l,int r,int rt) 54 { 55 if(l==r) return mi[rt]; 56 int mid=(l+r)>>1; pushdown(rt); 57 if(x<=mid) return query(x,l,mid,rt<<1); 58 else return query(x,mid+1,r,rt<<1|1); 59 } 60 }s; 61 62 int dis[N1],use[N1],fa[N1],la[N1],ist[M1*2]; 63 struct node{ 64 int id,d; 65 friend bool operator < (const node &s1,const node &s2) 66 {return s1.d>s2.d;} 67 }; 68 void dijkstra() 69 { 70 int j,v,u; 71 memset(dis,0x3f,sizeof(dis)); 72 priority_queue<node>q; 73 dis[1]=0,q.push((node){1,0}); 74 while(!q.empty()) 75 { 76 node k=q.top(); q.pop(); u=k.id; 77 if(use[u]) continue; use[u]=1; 78 for(j=E.head[u];j;j=E.nxt[j]){ 79 v=E.to[j]; 80 if(dis[v]>dis[u]+E.val[j]) 81 dis[v]=dis[u]+E.val[j],q.push((node){v,dis[v]}),fa[v]=u,la[v]=j; 82 } 83 } 84 } 85 86 int dep[N1],sz[N1],tp[N1],son[N1],st[N1],id[N1],tot; 87 void dfs1(int u,int dad) 88 { 89 for(int j=T.head[u];j;j=T.nxt[j]) 90 { 91 int v=T.to[j]; if(v==dad) continue; 92 dep[v]=dep[u]+1; dfs1(v,u); //fa[v]=u; 93 sz[u]+=sz[v]; son[u]=sz[v]>sz[son[u]]?v:son[u]; 94 } 95 sz[u]++; 96 } 97 void dfs2(int u) 98 { 99 st[u]=++tot,id[tot]=u; 100 if(son[u]) tp[son[u]]=tp[u],dfs2(son[u]); 101 for(int j=T.head[u];j;j=T.nxt[j]) 102 { 103 int v=T.to[j]; 104 if(v==son[u]||v==fa[u]) continue; 105 tp[v]=v; dfs2(v); 106 } 107 } 108 void update(int x,int y,int w) 109 { 110 int px=x,py=y; 111 while(tp[x]!=tp[y]) 112 { 113 if(dep[tp[x]]<dep[tp[y]]) swap(x,y); 114 s.update(st[tp[x]],st[x],1,n,1,dis[px]+dis[py]+w); 115 x=fa[tp[x]]; 116 } 117 if(dep[x]>dep[y]) swap(x,y); 118 if(x!=y) s.update(st[x]+1,st[y],1,n,1,dis[px]+dis[py]+w); 119 } 120 121 void solve() 122 { 123 int x,y,i,j,v,ans; dijkstra(); s.build(1,n,1); 124 for(i=2;i<=n;i++) T.ae(fa[i],i,E.val[la[i]]),ist[la[i]]=1; 125 dep[1]=1,dfs1(1,-1); tp[1]=1,dfs2(1); 126 for(j=2;j<=m*2;j+=2) 127 { 128 if(ist[j]||ist[j+1]) continue; 129 x=E.to[j],y=E.to[j+1]; 130 update(x,y,E.val[j]); 131 } 132 for(i=2;i<=n;i++) 133 { 134 ans=s.query(st[i],1,n,1); 135 if(ans==inf) printf("-1\n"); 136 else printf("%d\n",ans-dis[i]); 137 } 138 } 139 140 int main() 141 { 142 scanf("%d%d",&n,&m); 143 int i,j,x,y,z;E.cte=1; 144 for(i=1;i<=m;i++) x=gint(),y=gint(),z=gint(),E.ae(x,y,z),E.ae(y,x,z); 145 solve(); 146 return 0; 147 }