【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;
}

 

posted @ 2019-07-31 19:22  HellPix  阅读(...)  评论(...编辑  收藏