BZOJ 3732 Network
题解:求最大生成树,则边一定在最大生成树上,证明用Kluscal
然后就是倍增
TMD我竟然建树写错了,MDMDMDMDMDMD
为什么一开始没想到QWQ
总结:不要往难处想
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=30009; int n,m,T; struct Edge{ int u,v,d; }edges[maxn]; bool cmp(const Edge &rhs1,const Edge &rhs2){ return rhs1.d<rhs2.d; } int father[maxn]; int Getf(int x){ if(father[x]==x)return x; return father[x]=Getf(father[x]); } void Unionn(int x,int y){ int fx=Getf(x); int fy=Getf(y); if(fx!=fy)father[fx]=fy; } int cntedge; int head[maxn]; int to[maxn<<1],nex[maxn<<1],dist[maxn]; void Addedge(int x,int y,int z){ nex[++cntedge]=head[x]; to[cntedge]=y; dist[cntedge]=z; head[x]=cntedge; } int f[maxn][20],g[maxn][20],dep[maxn]; void Dfs(int now,int fa){ dep[now]=dep[fa]+1; for(int i=head[now];i;i=nex[i]){ if(to[i]==fa)continue; f[to[i]][0]=now; g[to[i]][0]=dist[i]; Dfs(to[i],now); } } void LCAinit(){ for(int j=1;j<=19;++j){ for(int i=1;i<=n;++i){ f[i][j]=f[f[i][j-1]][j-1]; g[i][j]=max(g[i][j-1],g[f[i][j-1]][j-1]); } } } int GetMaxd(int u,int v){ int ret=0; if(dep[u]<dep[v])swap(u,v); for(int j=19;j>=0;--j){ if(dep[f[u][j]]>=dep[v]){ ret=max(ret,g[u][j]); u=f[u][j]; } } if(u==v)return ret; for(int j=19;j>=0;--j){ if(f[u][j]!=f[v][j]){ ret=max(ret,max(g[u][j],g[v][j])); u=f[u][j];v=f[v][j]; } } return max(ret,max(g[u][0],g[v][0])); } int main(){ scanf("%d%d%d",&n,&m,&T); for(int i=1;i<=m;++i)scanf("%d%d%d",&edges[i].u,&edges[i].v,&edges[i].d); sort(edges+1,edges+1+m,cmp); for(int i=1;i<=n;++i)father[i]=i; for(int i=1;i<=m;++i){ int u=edges[i].u; int v=edges[i].v; int d=edges[i].d; if(Getf(u)==Getf(v))continue; Unionn(u,v); Addedge(u,v,d); Addedge(v,u,d); } Dfs(1,0); LCAinit(); // // for(int i=1;i<=n;++i){ // printf("%d %d\n",f[i][0],g[i][0]); // } while(T--){ int x,y; scanf("%d%d",&x,&y); printf("%d\n",GetMaxd(x,y)); } return 0; }
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!