题目大意:给定一张$n$个点$m$条有权边的无向联通图,$q$次询问两点间的最短路
$n\le100000$,$m\le100000$,$1\le100000$,$m$-$n\le20$.
首先看到$m$-$n\le20$这条限制,我们可以想到是围绕这个20来做这道题。
即如果我们随便在图上找一棵树,有最多21条非树边,连接最多42个顶点
考虑两点$x,y$之间的最短路就是某个点到$x$和$y$的最短路之和
首先对于只走树边的情况,这个点是两点的$LCA$
如果经过非树边,$x$或$y$到枚举的这个点的最短路上的最后一条边一定是非树边(如果都是树边的话完全可以转化到一个连接着非树边的点上去)
然后对于所有连接非树边的点都跑一遍最短路,询问时直接枚举这些点取$min$即可
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 #define M 200010 7 #define int long long 8 using namespace std; 9 int read() 10 { 11 char ch=getchar();int x=0; 12 while(ch>'9'||ch<'0') ch=getchar(); 13 while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=getchar(); 14 return x; 15 } 16 struct point{ 17 int to,next,dis; 18 }e[M<<1]; 19 int n,m,num,Q,top; 20 int q[M],head[M],deep[M],dist[M]; 21 int dis[50][M],fa[M][25]; 22 bool vis[M]; 23 struct node{int id,dis;}; 24 bool operator < (node a1,node a2) {return a1.dis>a2.dis;} 25 void add(int from,int to,int dis) 26 { 27 e[++num].next=head[from]; 28 e[num].to=to; 29 e[num].dis=dis; 30 head[from]=num; 31 } 32 void dfs(int x,int f) 33 { 34 vis[x]=true; fa[x][0]=f; 35 for(int i=head[x];i;i=e[i].next) 36 { 37 int to=e[i].to; 38 if(to==f) continue; 39 if(vis[to]) q[++top]=x,q[++top]=to; 40 else 41 { 42 deep[to]=deep[x]+1; 43 dist[to]=dist[x]+e[i].dis; 44 dfs(to,x); 45 } 46 } 47 } 48 int lca(int x,int y) 49 { 50 if(deep[x]<deep[y]) swap(x,y); 51 for(int i=19;i>=0;i--) 52 if(deep[fa[x][i]]>=deep[y]) 53 x=fa[x][i]; 54 if(x==y) return x; 55 for(int i=19;i>=0;i--) 56 if(fa[x][i]!=fa[y][i]) 57 x=fa[x][i],y=fa[y][i]; 58 return fa[x][0]; 59 } 60 void Dijkstra(int id) 61 { 62 memset(dis[id],63,sizeof(dis[id])); 63 memset(vis,false,sizeof(vis)); 64 priority_queue<node>Q; 65 dis[id][q[id]]=0; 66 Q.push((node){q[id],0}); 67 while(!Q.empty()) 68 { 69 int x=Q.top().id;Q.pop(); 70 if(vis[x]) continue; 71 vis[x]=true; 72 for(int i=head[x];i;i=e[i].next) 73 { 74 int to=e[i].to; 75 if(!vis[to]&&dis[id][x]+e[i].dis<dis[id][to]) 76 { 77 dis[id][to]=dis[id][x]+e[i].dis; 78 Q.push((node){to,dis[id][to]}); 79 } 80 } 81 } 82 } 83 #undef int 84 int main() 85 { 86 #define int long long 87 n=read(); m=read(); 88 for(int i=1;i<=m;i++) 89 { 90 int a=read(),b=read(),c=read(); 91 add(a,b,c); add(b,a,c); 92 } 93 deep[1]=1;dfs(1,0); 94 for(int j=1;j<=19;j++) 95 for(int i=1;i<=n;i++) 96 fa[i][j]=fa[fa[i][j-1]][j-1]; 97 sort(q+1,q+1+top); top=unique(q+1,q+1+top)-q-1; 98 for(int i=1;i<=top;i++) Dijkstra(i); 99 Q=read(); 100 while(Q--) 101 { 102 int x=read(),y=read(); 103 int ans=dist[x]+dist[y]-2*dist[lca(x,y)]; 104 for(int i=1;i<=top;i++) ans=min(ans,dis[i][x]+dis[i][y]); 105 printf("%lld\n",ans); 106 } 107 return 0; 108 }