和洛谷1967一样,只不过是求一个最小生成树,然后和上一道题一样,先构建新图,然后lca求到祖先距离的最大值
代码
//By AcerMo
#include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int M=700500; struct edge { int from,to,cost; bool friend operator < (edge a,edge b) { return a.cost>b.cost; } }now;//初始建图 priority_queue<edge>q; struct map { int to,cost; }_233;//新图 vector<map>v[M]; int n,m,que; int vis[M/4],deep[M/4],pt[M/4][22]; int fa[M/4],size[M/4],fatt[M/4][22]; int find(int x) { if (x!=fa[x]) return fa[x]=find(fa[x]); return x; } void unionn(int a,int b) { if (size[a]<=size[b]) size[b]+=size[a],fa[a]=b; else size[a]+=size[b],fa[b]=a; return ; }//加入了按秩合并以及路径压缩 void constt() { for (int i=0;i<=n;i++) size[i]=1,fa[i]=i,fatt[i][0]=i,deep[i]=1; return ; }//初始化每个点的信息 void kru() { int cnt=1;constt(); while (q.size()&&cnt<n) { now=q.top();q.pop(); int r1=find(now.from); int r2=find(now.to); if (r1!=r2) { unionn(r1,r2),cnt++; _233.to=now.to;_233.cost=now.cost;v[now.from].push_back(_233); _233.to=now.from;_233.cost=now.cost;v[now.to].push_back(_233); }//注意加入新图的是原点而不是祖先 } return ; }//最大生成树及构建新图 void getlca(int x) { vis[x]=1; for (int i=0;i<v[x].size();i++) { int go=v[x][i].to; if (vis[go]) continue; deep[go]=deep[x]+1; fatt[go][0]=x; pt[go][0]=v[x][i].cost; getlca(go); } return ; }//构建lca祖先关系 void getminpath() { for (int i=1;i<=20;i++) for (int k=1;k<=n;k++) { fatt[k][i]=fatt[fatt[k][i-1]][i-1]; pt[k][i]=max(pt[k][i-1],pt[fatt[k][i-1]][i-1]); } return ; }//预处理每个点到祖先的距离 int lca(int x,int y) { int ans=0; if (deep[x]>deep[y]) swap(x,y); for (int i=20;i>=0;i--) if (deep[fatt[y][i]]>=deep[x]) ans=max(ans,pt[y][i]),y=fatt[y][i]; if (x==y) return ans; for (int i=20;i>=0;i--) if (fatt[x][i]!=fatt[y][i]) ans=max(ans,max(pt[x][i],pt[y][i])), x=fatt[x][i],y=fatt[y][i]; ans=max(ans,max(pt[x][0],pt[y][0])); return ans; }//lca求解 int main() { scanf("%d%d%d",&n,&m,&que); for (int i=1;i<=m;i++) scanf("%d%d%d",&now.from,&now.to,&now.cost),q.push(now); kru(); for (int i=1;i<=n;i++) if (!vis[i]) getlca(i); getminpath(); while (que--) { int x,y; scanf("%d%d",&x,&y); int ans=lca(x,y); cout<<ans<<endl; } return 0; }