Luogu P1967 [NOIP2013]货车运输

题目
我们要求的是树上一条路径上的最短边权。
这东西有很多做法:
\(1.\)倍增维护。
\(2.\)建Kruskal重构树。
\(3.\)转化为按边权升序枚举,然后建并查集重构树。

#include<bits/stdc++.h>
#define open(file) freopen(file".in","r",stdin),freopen(file".out","w",stdout)
#define N 200007
using namespace std;
namespace IO
{
    char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
    char Get() { return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++); }
    void Flush() { fwrite(obuf,1,oS-obuf,stdout),oS=obuf; }
    void Put(char x) { *oS++=x; if(oS==oT) Flush(); }
    int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;}
    void write(int x) {int top=0; if(!x) Put('0'); while(x) st[++top]=(x%10)+48,x/=10; while(top) Put(st[top--]); Put('\n'); }
}
using namespace IO;
void print(){Put('-'),Put('1'),Put('\n');}
struct Edge{int u,v,w;}edge[N];
int operator<(Edge a,Edge b){return a.w>b.w;}
int head[N],tot,Fa[N],ver[N],Next[N],val[N],vis[N],dep[N],fa[N],size[N],son[N],top[N];
void add(int u,int v){ver[++tot]=v,Next[tot]=head[u],head[u]=tot;}
int Find(int x){return x==Fa[x]? x:Fa[x]=Find(Fa[x]);}
void dfs(int u,int Fa)
{
    size[u]=vis[u]=1;
    for(int i=head[u],v;i;i=Next[i]) if((v=ver[i])^Fa) dep[v]=dep[u]+1,fa[v]=u,dfs(v,u),size[u]+=size[v],son[u]=size[v]>size[son[u]]? v:son[u];
}
void Dfs(int u,int Top)
{
    top[u]=Top;
    if(son[u]) Dfs(son[u],Top);
    for(int i=head[u],v;i;i=Next[i]) if((v=ver[i])^son[u]&&v^fa[u]) Dfs(v,v);
}
int LCA(int u,int v)
{
    while(top[u]^top[v]) dep[top[u]]>dep[top[v]]? u=fa[top[u]]:v=fa[top[v]];
    return dep[u]>dep[v]? v:u;
}
int main()
{
    int n=read(),m=read(),cnt=n,i,Q,u,v;
    for(i=1;i<=m;++i) edge[i]=Edge{read(),read(),read()};
    sort(edge+1,edge+m+1);
    for(i=1;i<=n;++i) Fa[i]=i;
    for(i=1;i<=m;++i) if((u=Find(edge[i].u))^(v=Find(edge[i].v))) val[++cnt]=edge[i].w,Fa[cnt]=Fa[u]=Fa[v]=cnt,add(u,cnt),add(cnt,u),add(v,cnt),add(cnt,v);
    for(u=1;u<=cnt;++u) if(!vis[u]) dfs(v=Find(u),0),Dfs(v,v);
    for(Q=read();Q;--Q) u=read(),v=read(),Find(u)^Find(v)? print():write(val[LCA(u,v)]);
    return Flush(),0;
}

猜你喜欢

转载自www.cnblogs.com/cjoierShiina-Mashiro/p/11887098.html