Test instructions: Give you N a point M edge, m-n<=20, there are 1e5 inquiries, ask two points of the shortest distance. No self-loops and heavy edges are guaranteed.
Problem: Even the topic is prompt you this 20 is very useful, so if it is a tree, then the shortest distance of any two points is to ask for an LCA to engage in a problem. So we can first find the smallest spanning tree, then there will be a maximum of 42 points, we know that the non-tree edge may be better, so for each non-tree edge corresponding two points run over Dij, try to update the answer Ans=min (Ans,dis[i][u]+dis[i][v]). Correctness: Possible through multiple non-tree edges? In the run Dij in fact has been dealt with the shortest way, if it is more than the tree edge more excellent, then it records is such a value. Why is the code of the other person so short ...
#include <bits/stdc++.h> #define LL long long#define PB push_back#define ls x<<1#define rs x<<1|1# Define ull unsigned long long#define _mp make_pair#define ldb long doubleusing namespace Std;const int Maxn=1e5+100;const ll inf=1e18;int bcg[maxn];struct edge{int u,v,nxt; ll W;} Edge[maxn*2],edge1[maxn*2];vector<edge>vec[maxn];struct node{ll P; int V; friend bool operator< (Node A,node b) {return a.p>b.p; } node () {} node (ll x,int y) {p=x,v=y;}}; int head[maxn],head1[maxn];ll deep[maxn];int depth[maxn];int bian[maxn*2];ll dis[50][maxn];int lca[maxn][25];int vis[ Maxn];int cnt,cnt1,tot;int n,m;int findd (int x) {return bcg[x]==x?bcg[x]:bcg[x]=findd (bcg[x]);} BOOL CMP (Edge A,edge b) {return A.W<B.W;} void add_e1 (int x,int y,ll W) {++cnt1;edge1[cnt1].u=x;edge1[cnt1].v=y;edge1[cnt1].w=w;edge1[cnt1].nxt=head1[x]; Head1[x]=cnt1;} void add_e (int x,int y,ll W) {++cnt;edge[cnt].u=x;edge[cnt].v=y;edge[cnt].w=w;edge[cnt].nxt=head[x];head[x]=cnt;} int merges (int x,int y) {int xx=findd (x); int yy=findd (y); if (xx!=yy) {bcg[xx]=yy; return 1; } return 0;} void Init () {cnt=cnt1=0; tot=0; memset (deep,0,sizeof (deep)); memset (head,0,sizeof (head)); memset (head1,0,sizeof (Head1));} void Dfs (int x,int ff) {lca[x][0]=ff; for (int i=1;i<=20;i++) lca[x][i]=lca[lca[x][i-1]][i-1]; for (int i=head[x];i;i=edge[i].nxt) {int v=edge[i].v; if (V==FF) continue; DEEP[V]=DEEP[X]+EDGE[I].W; depth[v]=depth[x]+1; DFS (V,X); }}int LCA (int x,int y) {if (Depth[x]<depth[y]) swap (x, y); int ff=depth[x]-depth[y]; for (int i=20;i>=0;i--) {if (ff& (1<<i)) x=lca[x][i]; } if (x==y) return y; for (int i=20;i>=0;i--) {if (Lca[x][i]!=lca[y][i]) x=lca[x][i],y=lca[y][i]; } return lca[y][0];} Priority_queue<node>que;void dij (int id,int x) {for (int i=0;i<=n+4;i++) {dis[id][i]=inf; vis[i]=0; } dis[id][x]=0; while (!que.empty ()) Que.pop (); Que.push (Node (0,x)); while (!que.empty ()) {Node vv=que.top (); Que.pop (); if (vis[vv.v]| | VV.P>DIS[ID][VV.V]) continue; Vis[vv.v]=1; for (int i=0;i< (int) vec[vv.v].size (); i++) {Edge k=vec[vv.v][i]; int sw=k.v; if (VIS[SW]) continue; if (DIS[ID][SW]>DIS[ID][VV.V]+K.W) {DIS[ID][SW]=DIS[ID][VV.V]+K.W; Que.push (Node (DIS[ID][SW],SW)); }}}}int Main () {scanf ("%d%d", &n,&m); int u,v; ll W; Init (); for (int i=1;i<=m;i++) {scanf ("%d%d%lld", &u,&v,&w); Add_e1 (U,V,W); Vec[u].push_back (Edge) {u,v,0,w}); Vec[v].push_back (Edge) {v,u,0,w}); } sort (edge1+1,edge1+cnt1+1,cmp); for (int i=1;i<=n+4;i++) bcg[i]=i; for (int i=1;i<=cnt1;i++) {int x=edge1[i].u,y=edge1[i].v; if (merges (x, y)) { Add_e (X,Y,EDGE1[I].W); Add_e (Y,X,EDGE1[I].W); } else {bian[++tot]=x; Bian[++tot]=y; }} depth[1]=0; deep[1]=0; DFS (1,0); Sort (bian+1,bian+1+tot); int Sz=unique (Bian+1,bian+1+tot)-(bian+1); for (int i=1;i<=sz;i++) {dij (i,bian[i]); } int q; scanf ("%d", &q); int x, y; while (q--) {scanf ("%d%d", &x,&y); ll Ans=inf; int Pq=lca (x, y); ANS=DEEP[X]+DEEP[Y]-2*DEEP[PQ]; for (int i=1;i<=sz;i++) {ans=min (ans,dis[i][x]+dis[i][y]); } cout<<ans<< "\ n"; } return 0;}
Codeforces 1051E. Vasya and Big integers