迷宫花坛
题解:
代码
#include<bits/stdc++.h>
using namespace std;
int const N=1e5+10;
int const M=2e5+10;
struct edge{
int to,nt,w;
}e[M<<1],e2[M<<1];
int n,h[N],cnt,bl[N],q,f[N][17],m,st[N],top,lt[N],dist[N][17],num,rt[N],vis[N],id[N],cnt2,h2[N];
int tin[N],tout[N],sum;
vector<int> cycle[N],se[N];
map<pair<int,int>,int > mat;
map<pair<int,int>,int > :: iterator p;
void add(int a,int b,int c){
e[++cnt].to=b;
e[cnt].w=c;
e[cnt].nt=h[a];
h[a]=cnt;
}
void add2(int a,int b,int c){
e2[++cnt2].to=b;
e2[cnt2].w=c;
e2[cnt2].nt=h2[a];
h2[a]=cnt2++;
}
void dfs(int x,int fa,int d){
st[++top]=x;
lt[top]=d;
vis[x]=1;
for(int i=h[x];i;i=e[i].nt){
int v=e[i].to;
if(v==fa) continue;
if(vis[v] && !bl[v]){
num++;int k=0,tp=top;
rt[num]=v;
lt[top+1]=e[i].w;
int c=0;
while (1){
int t=st[top];
bl[t]=num;
id[t]=k;
int last=0;
if(k) last=cycle[num][k-1];
cycle[num].push_back(last+lt[top+1]);
se[num].push_back(t);
top--;
k++;
if(t==v) break;
}
top=tp;
}else if(!vis[v]) dfs(v,x,e[i].w);
}
if(!bl[x]) {
num++;
bl[x]=num;
id[x]=0;
rt[num]=x;
se[num].push_back(x);
cycle[num].push_back(0);
}
top--;
}
void dfs2(int x,int fa,int d){
f[x][0]=fa;
dist[x][0]=d;
tin[x]=++sum;
for(int i=h2[x];i;i=e2[i].nt){
int v=e2[i].to;
if(v==fa) continue;
dfs2(v,x,e2[i].w);
}
tout[x]=++sum;
}
int ancestor(int x,int y){
return tin[x]<=tin[y] && tout[y]<=tout[x];
}
int lca(int x,int y){
for(int i=16;i>=0;i--)
if(!ancestor(f[x][i],y))
x=f[x][i];
return x;
}
int calc(int x,int y){
if(x==y) return 0;
int res=0;
for(int i=16;i>=0;i--)
if(!ancestor(f[x][i],y)){
res+=dist[x][i];
x=f[x][i];
}
return res+dist[x][0];
}
int main(){
freopen("garden.in","r",stdin);
freopen("garden.out","w",stdout);
scanf("%d%d",&n,&m) ;
while (m--){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(x>y) swap(x,y);
if(mat.find(make_pair(x,y))==mat.end())
mat[make_pair(x,y)]=z;
else mat[make_pair(x,y)]=min(mat[make_pair(x,y)],z);
}
for(p=mat.begin();p!=mat.end();p++){
int x=p->first.first;
int y=p->first.second;
int z=p->second;
add(x,y,z);
add(y,x,z);
}
dfs(1,1,0);
for(int i=1;i<=n;i++)
for(int j=h[i];j;j=e[j].nt){
int x=i;
int y=e[j].to;
if(bl[x]!=bl[y]) add2(x,y,e[j].w);
}
for(int i=1;i<=num;i++)
for(int j=0;j<se[i].size();j++) {
int x=rt[bl[se[i][j]]];
int y=se[i][j];
if(x==y) continue;
int z=bl[se[i][j]];
int sz=cycle[z].size()-1;
int d=min(abs(cycle[z][id[x]]-cycle[z][id[y]]),cycle[z][sz]-abs(cycle[z][id[x]]-cycle[z][id[y]]));
add2(x,y,d);
add2(y,x,d);
}
dfs2(1,1,0);
for(int j=1;j<=16;j++)
for(int i=1;i<=n;i++){
f[i][j]=f[f[i][j-1]][j-1];
dist[i][j]=dist[i][j-1]+dist[f[i][j-1]][j-1];
}
scanf("%d",&q);
while (q--){
int x,y;
scanf("%d%d",&x,&y);
if(ancestor(x,y))
printf("%d\n",calc(y,x));
else if(ancestor(y,x))
printf("%d\n",calc(x,y));
else {
int t1=lca(x,y);
int t2=lca(y,x);
if(bl[t1]!=bl[t2])
printf("%d\n",calc(x,f[t1][0])+calc(y,f[t1][0]));
else {
int tmp=calc(x,t1)+calc(y,t2);
int z=bl[t1];
int a=id[t1];
int b=id[t2];
int sz=cycle[z].size()-1;
tmp+=min(abs(cycle[z][a]-cycle[z][b]),cycle[z][sz]-abs(cycle[z][a]-cycle[z][b]));
printf("%d\n",tmp);
}
}
}
return 0;
}