求仙人掌上的最短路径。
把每个环中间新建一个点连向各个点,再把原来的环中的点删了。。把这个新建的点叫方点,原来的点叫圆点。方点向原点连的边为每个点到这个圆环的dfs序最小的点的最短距离。(因为 dfs序最小的点最后位于top)
注意到新图是一颗树。
从新图一个原点dfs,再维护每个方点四周的圆环信息(推荐vector)。
每次查询直接查树上路径即可。注意到如果查的lca是方点,那么最短路径要在维护的圆环信息上去取值,这个直接lowerbound即可。也可以维护一个在圆环中的位置,查询直接查最短路径。
#include<bits/stdc++.h>
#include<tr1/unordered_map>
using namespace std;
typedef tr1::unordered_map<int,int> MP;
inline int rd(){
char ch=getchar();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}
return i*f;
}
inline void W(int x){
static int buf[50];
if(!x){putchar('0');return;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10;x/=10;}
while(buf[0]){putchar(buf[buf[0]--]+'0');}
}
const int N=1e5+50;
typedef pair<int,int> pii;
int n,m,q,tot;
int ban[N];
int vis[N],ind;
pii st[N];
int pos[N],len[N],tp;
MP pos_on_cir[N];
vector<int> cir[N];
int fa[N][23],dep[N],dis[N];
struct G{
int g[N],fm[N],nt[N],v[N],w[N],ec;
G():ec(1){}
inline void add(int x,int y,int c){
nt[++ec]=g[x]; g[x]=ec;
v[ec]=y; fm[ec]=x;
w[ec]=c;
}
inline void dfs(int x,int f,int c){
fa[x][0]=f; dep[x]=dep[f]+1; dis[x]=dis[f]+c;
for(int i=1;i<=20;i++)
fa[x][i]= fa[ fa[x][i-1] ][i-1];
for(int e=g[x];e;e=nt[e]){
if(v[e]==f)continue;
dfs(v[e],x,w[e]);
}
}
}g1,g2;
inline void dfs(int x,int f){
vis[x]=++ind;
for(int e=g1.g[x];e;e=g1.nt[e]){
if((vis[g1.v[e]] && vis[g1.v[e]]>vis[x]) || g1.v[e]==f)continue;
if(vis[g1.v[e]]){
++tot; cir[tot].push_back(g1.w[e]); pos_on_cir[tot][x]=0;
for(int i=tp;i>=pos[g1.v[e]];i--){
int sz=cir[tot].size()-1;
pos_on_cir[tot][ st[i].first ] = sz+1;
cir[tot].push_back(cir[tot][sz] +g1.w[st[i].second]);
}
int sz=cir[tot].size()-1,l=cir[tot][sz];
int d=cir[tot][0];d=min(d,l-d);
g2.add(tot,x,d); g2.add(x,tot,d);
for(int i=tp;i>=pos[g1.v[e]];i--){
d=cir[tot][ pos_on_cir[tot][st[i].first]];
d=min(l-d,d);
g2.add(tot,st[i].first,d);
g2.add(st[i].first,tot,d);
}
ban[e]= ban[e^1] = 1;
for(int i=tp;i>=pos[g1.v[e]];i--){
ban[st[i].second]= (ban[st[i].second^1] = 1);
}
}else{
pos[x]=++tp; st[tp]=make_pair(x,e);
dfs(g1.v[e],x); --tp;
}
}
}
inline int up(int x,int d){
for(int i=20;i>=0;i--)
if(d&(1<<i))x=fa[x][i];
return x;
}
inline int getlca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
x=up(x,dep[x]-dep[y]);
if(x==y)return x;
for(int i=20;i>=0;i--)
(fa[x][i]!=fa[y][i])&&(x=fa[x][i],y=fa[y][i]);
return fa[x][0];
}
inline int query_dis(int x,int y){
int lca=getlca(x,y);
if(lca<=n)return dis[x]+dis[y]-2*dis[lca];
int xc1=up(x,dep[x]-dep[lca]-1),yc1=up(y,dep[y]-dep[lca]-1);
int ans=dis[x]-dis[xc1]+dis[y]-dis[yc1];
int d=min(dis[xc1]-dis[lca]+dis[yc1]-dis[lca], abs(cir[lca][pos_on_cir[lca][yc1]] - cir[lca][pos_on_cir[lca][xc1]]));
return ans+d;
}
int main(){
n=rd(),m=rd(),q=rd(); tot=n;
for(int i=1;i<=m;i++){
int x=rd(),y=rd(),c=rd();
g1.add(x,y,c); g1.add(y,x,c);
}
dfs(1,0);
for(int i=2;i<=g1.ec;++i){
if(!ban[i]){
int u=g1.fm[i],v=g1.v[i],c=g1.w[i];
g2.add(u,v,c);
}
}
g2.dfs(1,0,0);
while(q--)
W(query_dis(rd(),rd())),putchar('\n');
}