题解:建立圆方树,每个点向环内深度最浅的点连边
分LCA是不是方点讨论即可
如果是方点讨论从哪边绕过去的
园点的话直接用最短路处理即可
问题:双联通分量不熟
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<map>
using namespace std;
const int maxn=100009;
const int inf=1000000000;
int n,m,T;
map<int,int>ma[maxn];
struct Edge{
int from,to,dist;
};
vector<int>G[maxn];
vector<Edge>edges;
void Addedge(int x,int y,int z){
Edge e;
e.from=x;e.to=y;e.dist=z;
edges.push_back(e);
G[x].push_back(edges.size()-1);
}
queue<int>q;
int inq[maxn];
int d[maxn];
void Spfa(){
for(int i=1;i<=n;++i){
d[i]=inf;inq[i]=0;
}
d[1]=0;inq[1]=1;q.push(1);
while(!q.empty()){
int x=q.front();q.pop();inq[x]=0;
for(int i=0;i<G[x].size();++i){
Edge e=edges[G[x][i]];
if(d[x]+e.dist<d[e.to]){
d[e.to]=d[x]+e.dist;
if(!inq[e.to]){
q.push(e.to);
inq[e.to]=1;
}
}
}
}
}
int dfsclock,scccnt;
int pre[maxn],lowlink[maxn],ref[maxn];
int lastpoint[maxn],restedge[maxn];
int S[maxn],top;
int dt[maxn];
int vis[maxn];
int depth[maxn];
int father[maxn];
vector<int>son[maxn];
void Dfs(int u,int fa){
// printf("now in point %d
",u);
// for(int i=1;i<=5e8;++i);
pre[u]=lowlink[u]=++dfsclock;
ref[dfsclock]=u;
S[++top]=u;
// cout<<u<<' '<<S.size()<<endl;
for(int i=0;i<G[u].size();++i){
Edge e=edges[G[u][i]];
// if(edges[G[u][i]^1].from==fa)continue;
int v=e.to;
if(v==fa)continue;
if(!pre[v]){
dt[v]=dt[u]+e.dist;
Dfs(v,u);
lowlink[u]=min(lowlink[u],lowlink[v]);
}else if(!vis[v]){
// cout<<u<<' '<<v<<endl;
lowlink[u]=min(lowlink[u],pre[v]);
restedge[u]=e.dist;
for(int i=top;S[i]!=v;--i){
int x=S[i];
// cout<<x<<' '<<v<<endl;
if(x==v)break;
father[x]=v;
lastpoint[x]=u;
son[v].push_back(x);
// printf("push(%d)
",x);
// if(S.size()==0)cout<<u<<endl;
}
}
}
// cout<<u<<" AFSD "<<S.size()<<endl;
if(lowlink[u]==pre[u]){
father[u]=fa;
son[fa].push_back(u);
// printf("push(%d)
",u);
}
--top;
vis[u]=1;
// printf("now out point %d
",u);
}
void Getdepth(int now,int fa){
depth[now]=depth[fa]+1;
for(int i=0;i<son[now].size();++i){
if(son[now][i]==fa)continue;
Getdepth(son[now][i],now);
}
}
int f[maxn][20];
void LCAinit(){
for(int i=1;i<=n;++i)f[i][0]=father[i];
for(int j=1;j<=19;++j){
for(int i=1;i<=n;++i){
f[i][j]=f[f[i][j-1]][j-1];
}
}
}
int Getlca(int x,int y){
if(depth[x]<depth[y])swap(x,y);
for(int j=19;j>=0;--j){
if(depth[f[x][j]]>=depth[y])x=f[x][j];
}
if(x==y)return x;
for(int j=19;j>=0;--j){
if(f[x][j]!=f[y][j]){
x=f[x][j];y=f[y][j];
}
}
return f[x][0];
}
int Getpoint(int x,int y){
for(int j=19;j>=0;--j){
if(depth[f[x][j]]>depth[y])x=f[x][j];
}
return x;
}
int Getans(int x,int y){
if(depth[x]<depth[y])swap(x,y);
int lca=Getlca(x,y);
// cout<<"lca="<<lca<<endl;
if(lca==y){
// if(d[x]-d[y]==6760174)cout<<"AD"<<endl;
return d[x]-d[y];
}
int px=Getpoint(x,lca);
int py=Getpoint(y,lca);
if((lastpoint[px]!=lastpoint[py])||(lastpoint[px]==0)||(lastpoint[py]==0)){
return d[x]+d[y]-2*d[lca];
}else{
int ans=d[x]+d[y]-d[px]-d[py];
int tmp;
if(dt[px]>dt[py])tmp=dt[px]-dt[py];
else tmp=dt[py]-dt[px];
// printf("%d %d
",lastpoint[px],restedge[lastpoint[px]]);
int ans1=ans+tmp;
int ans2=ans+restedge[lastpoint[px]]+dt[lastpoint[px]]-dt[ref[lowlink[px]]]-tmp;//6760174
if(ans2==6760174){
printf("tmp=%d lastpoint=%d ref[]=%d
",tmp,lastpoint[py],ref[lowlink[px]]);
}
return min(ans1,ans2);
}
}
int main(){
// freopen("cactus.in","r",stdin);
// freopen("cactus.out","w",stdout);
//
scanf("%d%d%d",&n,&m,&T);
while(m--){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(ma[x].count(y)){
ma[x][y]=min(ma[x][y],z);
}else if(ma[y].count(x)){
ma[y][x]=min(ma[y][x],z);
}else{
ma[x][y]=z;
}
}
for(int i=1;i<=n;++i){
for(map<int,int>::iterator it=ma[i].begin();it!=ma[i].end();++it){
Addedge(i,it->first,it->second);
Addedge(it->first,i,it->second);
}
}
Spfa();
Dfs(1,0);
Getdepth(1,0);
LCAinit();
// for(int i=1;i<=n;++i)cout<<depth[i]<<' ';
// cout<<endl;
while(T--){
int x,y;
scanf("%d%d",&x,&y);
printf("%d
",Getans(x,y));
}
return 0;
}