【P1843】货车运输(最大生成树+LCA)

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
struct Edge
{
    int u,v,limit;
    inline void Read()
    {
        scanf("%d%d%d",&u,&v,&limit);
    }
}Sed[50004];
int son[10004];
struct Edge2
{
    int link,next,limit;
}ed[50004];
int Ecnt;
inline void Add(int u,int v,int l)
{
    ed[++Ecnt].link=v,ed[Ecnt].limit=l,ed[Ecnt].next=son[u];
    son[u]=Ecnt;
}
int f[10004],h[10004],d[10004],fa[10004],ll[10004];
int getf(int x)
{
    if (f[x]==x) return x;
    return f[x]=getf(f[x]);
}
void Get_Dep(int x,int dep)
{
    d[x]=dep;
    for (int i=son[x];i;i=ed[i].next) Get_Dep(ed[i].link,dep+1),fa[ed[i].link]=x,ll[ed[i].link]=ed[i].limit;
}
const int INF=~0U>>4;
int Get_Ans(int u,int v)                         //LCA
{
    int x=u,y=v,ans=INF;
    while (x!=y)
    {
        if (d[x]<d[y]) y=fa[y];
        else if (d[x]>d[y]) x=fa[x];
        else x=fa[x],y=fa[y];
    }
    while (u!=x) ans=min(ans,ll[u]),u=fa[u];
    while (v!=y) ans=min(ans,ll[v]),v=fa[v];
    return ans;
}
inline bool cmp(const Edge& A,const Edge& B)
{
    return A.limit>B.limit;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
        Sed[i].Read();
    for (int i=1;i<=n;i++)//预处理
        h[i]=0,f[i]=i;
    sort(Sed+1,Sed+m+1,cmp);
    for (int i=1;i<=m;i++)           //构树
    {
        Edge x=Sed[i];
        int u=getf(x.u),v=getf(x.v);
        if (u==v) continue;
        if (h[u]>h[v]) Add(u,v,x.limit),f[f[v]]=u;
        else if (h[u]<h[v]) Add(v,u,x.limit),f[f[u]]=v;
        else Add(u,v,x.limit),h[u]++,f[f[v]]=u;
    }
    for (int i=1;i<=n;i++)
        if (f[i]==i) Get_Dep(i,1);
    int q;
    scanf("%d",&q);
    for (int i=1,u,v;i<=q;i++)
    {
        scanf("%d%d",&u,&v);
        if (getf(u)!=getf(v))
        {
            puts("-1");
            continue;
        }
        printf("%d\n",Get_Ans(u,v));
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值