【BZOJ2125】最短路
题面
http://darkbzoj.tk/problem/2125
题解
#include<cstdio> #include<cstring> #include<iostream> #include<vector> #include<cstdlib> #include<stack> #define ri register int #define N 50500 #define M 105000 using namespace std; int tn,n,m,q; inline int read() { int ret=0,f=0; char ch=getchar(); while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&& ch<='9') ret*=10,ret+=ch-'0',ch=getchar(); return f?-ret:ret; } int ciren[N]; bool zheng[N]; struct tree { vector<int> to[N<<1],len[N<<1]; void add_edge(int u,int v,int w) { to[v].push_back(u); len[v].push_back(w); } int fa[N<<1],f[N<<1][19],d[N<<1]; int sL[N<<1]; void maketree(int x,int ff) { f[x][0]=fa[x]=ff; for (ri i=1;i<=18;i++) f[x][i]=f[f[x][i-1]][i-1]; for (ri i=0;i<to[x].size();i++) { int y=to[x][i]; sL[y]=sL[x]+len[x][i]; d[y]=d[x]+1; maketree(y,x); } } int lca(int x,int y) { if (d[x]<d[y]) swap(x,y); for (ri i=18;i>=0;i--) if (d[f[x][i]]>=d[y]) x=f[x][i]; if (x==y) return x; for (ri i=18;i>=0;i--) if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return fa[x]; } int jump(int x,int y) { for (ri i=18;i>=0;i--) if (d[f[x][i]]>d[y]) x=f[x][i]; return x; } int query(int x,int y) { int t=lca(x,y); if (t>tn) { int x0=jump(x,t); int y0=jump(y,t); int ans=sL[x]-sL[x0]+sL[y]-sL[y0]; if (zheng[x0]!=zheng[y0]) { ans+=min(sL[x0]+sL[y0]-2*sL[t],ciren[t]-sL[x0]-sL[y0]+2*sL[t]); } else { ans+=min(abs(sL[x0]-sL[y0]),ciren[t]-abs(sL[x0]-sL[y0])); } return ans; } else return sL[x]+sL[y]-2*sL[t]; } } T; struct graph { vector<int> to[N],len[N]; int dfn[N],low[N],dr[N]; int cnt; stack<int> s; void add_edge(int u,int v,int w) { to[u].push_back(v); len[u].push_back(w); to[v].push_back(u); len[v].push_back(w); } void tarjan(int x) { dfn[x]=low[x]=++cnt; s.push(x); for (ri i=0;i<to[x].size();i++) { int y=to[x][i]; if (dfn[y]) { low[x]=min(low[x],dfn[y]); } else { dr[y]=dr[x]+len[x][i]; tarjan(y); if (low[y]>=dfn[x]) { ++n; int t=s.top(),cirl=dr[t]-dr[x]; for (ri j=0;j<to[t].size();j++) if (to[t][j]==x) {cirl+=len[t][j]; break;} ciren[n]=cirl; do { t=s.top(); s.pop(); if (dr[t]-dr[x]>cirl-dr[t]+dr[x]) zheng[t]=1; T.add_edge(t,n,min(dr[t]-dr[x],cirl-dr[t]+dr[x])); } while (t!=y); T.add_edge(n,x,0); } low[x]=min(low[x],low[y]); } } } } G; int main() { int u,v,w; tn=n=read(); m=read(); q=read(); for (ri i=1;i<=m;i++) { u=read(); v=read(); w=read(); G.add_edge(u,v,w); } G.cnt=0; G.dr[1]=0; G.tarjan(1); T.maketree(1,1); for (ri i=1;i<=q;i++) { int u=read(), v=read(); printf("%d\n",T.query(u,v)); } return 0; }