bzoj3732: Network kruskal重构树
学了一波操作,学习网址:传送门
code:
#include<bits/stdc++.h> using namespace std; struct bia { int x,y,v; }; bia b[60010]; bool cmp(bia aa,bia bb){return aa.v<bb.v;} struct one { int y,next; }; one e[60010]; int n,m,k,d[30010],p=0,tot,pp[30010][22],z[30010],fa[30010],len=0,lin[30010]; int getfather(int pp) {if(pp==fa[pp])return pp;else return fa[pp]=getfather(fa[pp]);} void dfs(int t,int dp) { d[t]=dp; for(int i=lin[t];i;i=e[i].next) { pp[e[i].y][0]=t; dfs(e[i].y,dp+1); } } void insert(int x,int y) { e[++len].next=lin[x]; lin[x]=len; e[len].y=y; } void kruskal() { for(int i=1;i<=n;i++)fa[i]=i; tot=0;p=n; int f1,f2,i=0; while(tot<n-1) { i++; f1=getfather(b[i].x); f2=getfather(b[i].y); if(f1!=f2) { tot++;p++;z[p]=b[i].v; fa[p]=p;fa[f1]=p;fa[f2]=p; insert(p,f1); insert(p,f2); } } } void init() { for(int i=1;(1<<i)<=n;i++) { for(int j=1;j<=p;j++) pp[j][i]=pp[pp[j][i-1]][i-1]; } } int lca(int xx,int yy) { if(d[xx]>d[yy])swap(xx,yy); int ff=d[yy]-d[xx]; for(int i=0;(1<<i)<=ff;i++)if(((1<<i)&ff))yy=pp[yy][i]; if(xx==yy)return xx; else { for(int i=log(p);i>=0;i--) { if(pp[xx][i]!=pp[yy][i]) {xx=pp[xx][i];yy=pp[yy][i];} } return pp[xx][0]; } } int main() { //freopen("xf.in","r",stdin); //freopen("xf.out","w",stdout); scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=m;i++)scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].v); sort(b+1,b+m+1,cmp);kruskal(); dfs(p,0); init(); for(int i=1;i<=k;i++) { int x,y; scanf("%d%d",&x,&y); printf("%d\n",z[lca(x,y)]); } return 0; }