【题意】实在不想说这个题了,RE无数发。
【解题方法】就是求一个MST,把这个MST上的所有点标记之后,预处理距离和fa的关系,对于每一个查询先求LCA,然后在这个路径上维护最小值就行了。
【AC 代码】
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
const int maxn=10005;
const int inf=100000010;
int N,M,x,y,z,q;
struct edge
{
int u,v,w;
};
vector<edge>E;
int pa[maxn],fa[maxn],d[maxn],dep[maxn];
bool vis1[maxn];
vector<int>g[maxn],w[maxn];
void initial() //并查集初始化
{
for(int i=1; i<=N; i++)
pa[i]=i;
}
bool cmp(edge aa,edge bb) //按边权由大到小排序
{
return aa.w>bb.w;
}
int find(int x)
{
if(x==pa[x]) return x;
else return pa[x]=find(pa[x]);
}
bool check(int x,int y)
{
if(find(x)==find(y)) return 1;
return 0;
}
void bing(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx!=fy) pa[fx]=fy;
}
void kruskal()
{
initial();
memset(vis1,0,sizeof(vis1));
sort(E.begin(),E.end(),cmp);
for(int i=0; i<E.size(); i++)
{
if(!check(E[i].u,E[i].v))
{
bing(E[i].u,E[i].v);
g[E[i].u].push_back(E[i].v);
w[E[i].u].push_back(E[i].w);
g[E[i].v].push_back(E[i].u);
w[E[i].v].push_back(E[i].w);
vis1[E[i].u]=1;
vis1[E[i].v]=1;
}
}
}
void DFS(int i,int f,int de)
{
fa[i]=f;
dep[i]=de;
for(int k=0; k<g[i].size(); k++)
{
int j=g[i][k],c=w[i][k];
if(fa[i]==j) continue;
d[j]=d[i]+c;
DFS(j,i,de+1);
}
}
int LCA(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
while(dep[x]!=dep[y]) x=fa[x];
while(x!=y) x=fa[x],y=fa[y];
return x;
}
int getmin(int x,int y)
{
int z=LCA(x,y);
int mint=inf;
while(x!=z)
{
mint=min(mint,d[x]-d[fa[x]]);
x=fa[x];
}
while(y!=z)
{
mint=min(mint,d[y]-d[fa[y]]);
y=fa[y];
}
return mint;
}
int main()
{
cin>>N>>M;
for(int i=1; i<=M; i++)
{
cin>>x>>y>>z;
E.push_back((edge)
{
x,y,z
});
}
kruskal();
for(int i=1; i<=N; i++)
if(vis1[i]==1)
{
DFS(i,i,1);
break;
}
cin>>q;
while(q--)
{
cin>>x>>y;
if(check(x,y)==0) puts("-1");
else
{
cout<<getmin(x,y)<<endl;
}
}
//return 0;
}