分析
先求最大生成树,把一些多余的边去掉
求最近公共祖先LCA 可用树上倍增的方法 (Tarjan好像也行不知道会不会超时
询问前处理
w[i][j]=min(w[f[i][j-1]][j-1],w[i][j-1])
最后对于询问的x,y返回ans
ans=min(ans,w[i][j]) (w[i][j]在x,y到lca(x,y)路径上)
可能有一点点玄学,具体看代码就清楚 更玄学 啦~
代码如下
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=10005,inf=0x3f3f3f3f;
struct E{
int x,y,val;
}edge[50005];
struct tree{
int ver,to,w;
}edge2[100050];
int n,m,tot=0,p,head[N],t;
int fa[N],f[N][21],w[N][21],d[N];
int read(){
int sum=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
sum=(sum<<3)+(sum<<1)+ch-'0';
ch=getchar();
}
return sum*f;
}
bool comp(E a,E b){
return a.val>b.val;
}
int find(int x){
if(x==fa[x])return x;
return fa[x]=find(fa[x]);
}
void add(int x,int y,int z){
edge2[++tot].ver=y;
edge2[tot].to=head[x];
edge2[tot].w =z;
head[x]=tot;
}
void kruskal(){
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=m;i++)
{
int x=find(edge[i].x);
int y=find(edge[i].y);
if(x==y)continue;
fa[x]=y;
add(edge[i].x,edge[i].y,edge[i].val);
add(edge[i].y,edge[i].x,edge[i].val);
}
}
void dfs(int x)
{
for(int i=head[x];i;i=edge2[i].to) {
int y=edge2[i].ver;
if(d[y])continue;
d[y]=d[x]+1;
f[y][0]=x;
w[y][0]=edge2[i].w;
dfs(y);
}
}
int lca(int x,int y){
int ans=inf;
if(find(x)!=find(y))return -1;
if(d[x]>d[y])swap(x,y);
for(int i=t;i>=0;i--)
if(d[f[y][i]]>=d[x]){
ans=min(ans,w[y][i]);
y=f[y][i];
}
if(x==y)return ans;
for(int i=t;i>=0;i--){
if(f[x][i]!=f[y][i]){
ans=min(ans,w[x][i]);
ans=min(ans,w[y][i]);
x=f[x][i];y=f[y][i];
}
}
ans=min(ans,min(w[x][0],w[y][0]));
return ans;
}
void init(){
for(int i=1;i<=n;i++)
{
if(!d[i]){
d[i]=1;
f[i][0]=i;
w[i][0]=inf;
dfs(i);
}
}
for(int i=1;i<=t;i++)
for(int j=1;j<=n;j++)
{
f[j][i]=f[f[j][i-1]][i-1];
w[j][i]=min(w[f[j][i-1]][i-1],w[j][i-1]);
}
}
int main(){
// freopen("truck.in","r",stdin);
// freopen("truck.out","w",stdout);
n=read();
m=read();
int x,y,z;
t=(int)(log(n)/log(2))+1;
for(int i=1;i<=m;i++)
{
edge[i].x=read();
edge[i].y=read();
edge[i].val=read();
}
sort(edge+1,edge+m+1,comp);
kruskal();
init();
p=read();
for(int i=1;i<=p;i++)
{
x=read();
y=read();
cout<<lca(x,y)<<endl;
}
return 0;
}