BZOJ2125 最短路
生活随笔
收集整理的這篇文章主要介紹了
BZOJ2125 最短路
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
每個(gè)點(diǎn)有兩個(gè)值,一個(gè)是從根到這個(gè)點(diǎn)的最短路d[i],一個(gè)是從根沿dfs樹(shù)到這個(gè)點(diǎn)的距離rd[i].
之后是一個(gè)很牛逼的建圖,把環(huán)上的點(diǎn)都連到環(huán)中深度最淺的點(diǎn)得到一顆樹(shù),并維護(hù)每個(gè)點(diǎn)所在的環(huán)以及每個(gè)環(huán)的環(huán)長(zhǎng)。
對(duì)于一個(gè)詢問(wèn)(x,y),假設(shè)dep[x]>dep[y],分情況:
1.如果x和y的lca是y,那么答案為d[x]-d[y].
2.如果x和y的lca沒(méi)在環(huán)里,那么答案為d[x]+d[y]-2*d[lca].
3.如果x和y的lca在環(huán)里,設(shè)x,y向上走遇到的第一個(gè)環(huán)上節(jié)點(diǎn)分別是a,b,那么答案為d[x]-d[a]+d[y]-d[b]+min(abs(rd[a]-rd[b]),環(huán)長(zhǎng)-abs(rd[a]-rd[b])).
#include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std;const int N=10005,M=100005; int n,m,q,e=1,x,y,z,ti,cn,hd[N],nx[M],to[M],w[M],dl[M],dfn[N],st[N],d[N],v[N],rd[N],dp[N],bl[N],ln[N],f[N][14]; void ad(int x,int y,int z) {to[++e]=y,w[e]=z,nx[e]=hd[x],hd[x]=e;}void spfa() {memset(d,0x3f,sizeof d);queue<int> q; q.push(1),d[1]=0;while(!q.empty()) {int u=q.front(); q.pop();v[u]=0;for(int i=hd[u];i;i=nx[i]) if(d[to[i]]>d[u]+w[i]) {d[to[i]]=d[u]+w[i];if(!v[to[i]]) v[to[i]]=1,q.push(to[i]);}} } void gt(int x,int y) {if(x==y) return;bl[x]=cn,ad(y,x,0),dl[st[x]]=dl[st[x]^1]=1,ln[cn]+=w[st[x]],gt(to[st[x]^1],y); } void dfs(int x) {dfn[x]=++ti;for(int i=hd[x];i;i=nx[i]) if(i!=(st[x]^1)&&i<=m*2+1) {if(!dfn[to[i]]) rd[to[i]]=rd[x]+w[i],st[to[i]]=i,dfs(to[i]);else if(dfn[to[i]]<dfn[x]) ln[++cn]=w[i],gt(x,to[i]);} } void dfs2(int x) {for(int i=hd[x];i;i=nx[i]) if(!dl[i]&&!dp[to[i]]) f[to[i]][0]=x,dp[to[i]]=dp[x]+1,dfs2(to[i]); }int qry(int x,int y) {if(dp[x]<dp[y]) swap(x,y);int a=x,b=y;for(int i=13;~i;i--) if(dp[f[x][i]]>=dp[y]) x=f[x][i];if(x==y) return d[a]-d[b];for(int i=13;~i;i--) if(f[x][i]^f[y][i]) x=f[x][i],y=f[y][i];if(bl[x]&&bl[x]==bl[y]) {int r=abs(rd[x]-rd[y]);return d[a]-d[x]+d[b]-d[y]+min(r,ln[bl[x]]-r);}return d[a]+d[b]-2*d[f[x][0]]; }int main() {scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=m;i++) scanf("%d%d%d",&x,&y,&z),ad(x,y,z),ad(y,x,z);spfa(),dfs(1),dp[1]=1,dfs2(1);for(int j=1;j<14;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];while(q--) scanf("%d%d",&x,&y),printf("%d\n",qry(x,y));return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/juruolty/p/6438695.html
總結(jié)
以上是生活随笔為你收集整理的BZOJ2125 最短路的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 1.15 Python基础知识 - 函数
- 下一篇: 无向图强联通分量-洛谷 P2860 [U