# CF1051F The Shortest Statement

## 题意简化

$$1<=q,n,m<=10^5, 0<=m-n<=20$$

## 代码

#include<bits/stdc++.h>
using namespace std;
#define re register
#define ll long long
#define in inline
#define get getchar()
{
int t=0; char ch=get;
while(ch<'0' || ch>'9') ch=get;
while(ch<='9' && ch>='0') t=t*10+ch-'0', ch=get;
return t;
}
const int _=2e5+6;
struct edge1{
int x,y,w;
}ed[_];
struct edge{
int to,ne,w;
}e[_];
int n,m,fa[_],flag[_],tot,h[_];
in int find(int x)
{
if(fa[x]==x) return x;
fa[x]=find(fa[x]);
return fa[x];
}
in int cmp(edge1 a,edge1 b) {return a.w==b.w?a.x<b.x:a.w<b.w;}
in void add(int x,int y,int z)
{
e[++tot].to=y,e[tot].ne=h[x],e[tot].w=z,h[x]=tot;
}
in void kruskal()
{
for(re int i=1;i<=n;i++) fa[i]=i;
sort(ed+1,ed+m+1,cmp);
for(re int i=1;i<=m;i++) {
int fx=find(ed[i].x),fy=find(ed[i].y);
if(fx!=fy) {
fa[fx]=fy;
}
else
flag[i]=1;
}
}
int vis[_],f[_][25],cnt,dep[_];
ll d[_],dis[50][_];
in void dfs(int u)
{
vis[u]=1;
for(re int i=h[u];i;i=e[i].ne) {
int v=e[i].to;
if(!vis[v]&&v!=u){
f[v][0]=u;
d[v]=d[u]+e[i].w;
dep[v]=dep[u]+1;
dfs(v);}
}
}
in void prepare()
{
dep[1]=1;
dfs(1);
for(re int j=1;j<=20;j++)
for(re int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
}
in void dijkstra(int k,int rt)
{
memset(vis,0,sizeof(vis));
dis[k][rt]=0;
priority_queue<pair<ll,int > >q;
q.push(make_pair(0,rt));
while(!q.empty())
{
int u=q.top().second;q.pop();
if(vis[u])continue;
vis[u]=1;
for(re int i=h[u];i;i=e[i].ne)
{
int v=e[i].to;
if(dis[k][v]>dis[k][u]+e[i].w)
{
dis[k][v]=dis[k][u]+e[i].w;
q.push(make_pair(-dis[k][v],v));
}
}
}
}
in void work()
{
for(re int i=1;i<=m;i++)
if(flag[i]==1)
for(re int i=1;i<=m;i++)    {
if(flag[i]) {
dijkstra(++cnt,ed[i].x);    //每个端点跑dijkstra
dijkstra(++cnt,ed[i].y);
}
}
}
in int lca(int x,int y)
{

if(dep[x]>dep[y]) swap(y,x);
for(re int i=20;i>=0;i--)
if(dep[f[y][i]]>=dep[x])y=f[y][i];
if(x==y) return x;
for(re int i=20;i>=0;i--)
if(f[y][i]!=f[x][i]) y=f[y][i], x=f[x][i];
return f[x][0];
}
in void get_ans()
{
for(re int i=1;i<=q;i++) {
int k=lca(x,y); //求出LCA
ll ans=d[x]-2*d[k]+d[y];//求树上距离
for(re int j=1;j<=cnt;j++)
ans=min(dis[j][x]+dis[j][y],ans); //枚举每种经过非树边端点的情况
printf("%lld\n",ans);
}
}
int main()
{
memset(dis,0x7f,sizeof(dis));