1 条题解
-
0

// Kruskal 重构树 O(MlogM+NlogN) #include<bits/stdc++.h> using namespace std; const int N=30005,M=60005; //重构树 点数=2N,边数=4N int idx,h[N],to[M],ne[M]; void add(int u,int v){ to[++idx]=v;ne[idx]=h[u];h[u]=idx; to[++idx]=u;ne[idx]=h[v];h[v]=idx; } int n,m,q,p,val[N]; //val新建点点权 struct E{int x,y,w;}e[M]; //原图边 int pa[N]; //并查集数组 int dep[N],fa[N][21]; //树上倍增数组 int find(int x){ //并查集查找 return pa[x]==x?x:pa[x]=find(pa[x]); } void kruskal(){ for(int i=1;i<=n;++i) pa[i]=i; sort(e+1,e+1+m,[&](E a,E b){return a.w<b.w;}); for(int i=1;i<=m;++i){ int x=find(e[i].x),y=find(e[i].y); if(x!=y){ val[++p]=e[i].w; //新建点点权=边权 pa[p]=pa[x]=pa[y]=p; //点x,y均指向点p add(p,x); add(p,y); //x,y均与p连无向边 } } } void dfs(int x,int f){ //预处理dep,fa数组 dep[x]=dep[f]+1; fa[x][0]=f; for(int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for(int i=h[x];i;i=ne[i]){ int y=to[i]; if(y!=f) dfs(y,x); } } int lca(int x,int y){ //倍增求lca if(dep[x]<dep[y]) swap(x,y); //让x更深 for(int i=20;i>=0;i--)if(dep[fa[x][i]]>=dep[y]) x=fa[x][i]; //x向上跳到y的同一层 if(x==y) return x; for(int i=20;i>=0;i--)if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; //x,y一起向上跳 return fa[x][0]; } int main(){ ios::sync_with_stdio(0);cin.tie(0); cin>>n>>m>>q; for(int i=1,u,v,w;i<=m;++i){ cin>>u>>v>>w; e[i]={u,v,w}; } p=n; //新建点编号初值 kruskal();//重构树 dfs(p,0); //倍增预处理dep,fa数组 for(int u,v;q--;){ cin>>u>>v; printf("%d\n",val[lca(u,v)]); } }
- 1
信息
- ID
- 12488
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 3
- 上传者