货车运输(最大生成树+倍增)

题面

原题

Solution

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<queue>
#include<algorithm>
#define ll long long
#define re register
using namespace std;
inline int gi(){
    int f=1,sum=0;char ch=getchar();
    while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return f*sum;
}
const int N=10010,M=50010;
int to[M<<1],nxt[M<<1],w[M<<1],front[N],cnt;
int dep[N],f[N][20],val[N][20],father[N],n,m;
struct E{
    int u,v,w;
}edge[M];
void Add(int u,int v,int W){
    to[++cnt]=v;nxt[cnt]=front[u];front[u]=cnt;
    w[cnt]=W;
}
void dfs(int u,int fa){
    dep[u]=dep[fa]+1;f[u][0]=fa;
    for(re int i=front[u];i;i=nxt[i]){
        int v=to[i];
        if(v!=fa){
            val[v][0]=w[i];
            dfs(v,u);f[v][0]=u;
        }
    }
}
int lca(int u,int v){
    int ans=2e9;
    if(dep[u]<dep[v])swap(u,v);
    for(int i=15;~i;--i)
        if(dep[u]-(1<<i)>=dep[v]){
            ans=min(ans,val[u][i]);
            u=f[u][i];
        }
    if(u==v)return ans;
    for(re int i=15;~i;i--)
        if(f[u][i]!=f[v][i]){
            ans=min(ans,min(val[v][i],val[u][i]));
            u=f[u][i],v=f[v][i];
        }
    ans=min(ans,min(val[u][0],val[v][0]));
    return ans;
}
int find(int x){
    if(father[x]!=x)father[x]=find(father[x]);
    return father[x];
}
bool cmp(E a,E b){
    return a.w>b.w;
}
int main(){
    n=gi();m=gi();
    for(re int i=1;i<=m;i++){
        int u=gi(),v=gi(),w=gi();
        edge[i]=(E){u,v,w};
    }
    sort(edge+1,edge+m+1,cmp);
    for(re int i=1;i<=n;i++)father[i]=i;
    for(re int i=1;i<=m;i++){
        int u=find(edge[i].u),v=find(edge[i].v);
        if(u!=v){
            father[v]=u;
            Add(edge[i].u,edge[i].v,edge[i].w);
            Add(edge[i].v,edge[i].u,edge[i].w);
        }
    }
    for(re int i=1;i<=n;i++)
        if(!f[i][0]){
            dfs(i,i);val[i][0]=2e9;f[i][0]=i;
        }
    for(re int i=1;i<=15;i++)
        for(re int j=1;j<=n;j++){
            f[j][i]=f[f[j][i-1]][i-1];
            val[j][i]=min(val[f[j][i-1]][i-1],val[j][i-1]);
        }
    int q=gi();
    while(q--){
        int u=gi(),v=gi();
        if(find(u)!=find(v)){
            printf("%d
",-1);continue;
        }
        printf("%d
",lca(u,v));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cjgjh/p/9867635.html