标签:read problem getch 司机 ons 最大生成树 visit lin 倍增
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
int n,m,Q;
int f[10005][21],dis[10005][21],visit[10005],deep[10005];
int tot,head[10005],nxt[20005],to[20005],w[20005],fa[10005];
struct EDGE{
int from,to,w;
}e[50005];
inline void add(int a,int b,int c){
tot++;nxt[tot]=head[a];head[a]=tot;to[tot]=b;w[tot]=c;
tot++;nxt[tot]=head[b];head[b]=tot;to[tot]=a;w[tot]=c;
}
bool cmp(const EDGE &a,const EDGE &b){return a.w>b.w;}
inline int find(int x){
if(x==fa[x])return x;
return fa[x]=find(fa[x]);
}
inline void kruskal(){
int k=0;
sort(e+1,e+m+1,cmp);
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++){
int a=find(e[i].from),b=find(e[i].to);
if(a!=b){
add(a,b,e[i].w);
fa[b]=a;
k++;
if(k==n-1)break;
}
}
return;
}
void dfs(int u){
visit[u]=1;
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(visit[v])continue;
deep[v]=deep[u]+1;
f[v][0]=u;dis[v][0]=w[i];
dfs(v);
}
return;
}
int lca(int x,int y){
int ans=1e9;
if(deep[x]<deep[y])swap(x,y);
for(int i=20;i>=0;i--){
if(deep[f[x][i]]>=deep[y]){
ans=min(ans,dis[x][i]);//一定先更新ans,再让x,y往上跳,下面同理.
x=f[x][i];
}
}
if(x==y)return ans;
for(int i=20;i>=0;i--){
if(f[x][i]!=f[y][i]){
ans=min(ans,min(dis[x][i],dis[y][i]));
x=f[x][i];y=f[y][i];
}
}
ans=min(ans,min(dis[x][0],dis[y][0]));
return ans;
}
int main(){
n=read();m=read();
for(int i=1;i<=m;i++){
e[i].from=read();
e[i].to=read();
e[i].w=read();
}
kruskal();//构建最大生成树
for(int i=1;i<=n;i++){
if(visit[i])continue;
deep[i]=1;
dfs(i);
f[i][0]=i;dis[i][0]=1e9;
}//预处理,有些点不一定连通(即有可能是森林)
for(int j=1;j<=20;j++)
for(int i=1;i<=n;i++){
f[i][j]=f[f[i][j-1]][j-1];
dis[i][j]=min(dis[i][j-1],dis[f[i][j-1]][j-1]);
}//LCA的预处理
Q=read();
while(Q--){
int x=read(),y=read();
if(find(x)!=find(y))puts("-1");
else printf("%d\n",lca(x,y));
}
return 0;
}
标签:read problem getch 司机 ons 最大生成树 visit lin 倍增
原文地址:https://www.cnblogs.com/PPXppx/p/10542860.html