JZOJ1738. Heatwave

1738. Heatwave

题解

先做一遍最小生成树(Kruscal),再求每个询问中两点到他们的LCA的路径上边的最大值。

SRC

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

#define N 15000+10
#define M 40000+10
struct Etype{
    int u,v,d;
}E[M];
const int MX=15;

int Node[M],Next[M],D[M],Head[N],tot;
int f[N];
int Fa[N][20],V[N][20],H[N];
int n,m,Q;

bool cmp(Etype a,Etype b) {return a.d < b.d ;}

void Swap(int *a,int *b) {int t=*a; *a=*b; *b=t;}

void link(int u,int v,int w) {
    Node[++tot]=v;
    D[tot]=w;
    Next[tot]=Head[u];
    Head[u]=tot;
}

int getfather(int x) {
    if(f[x]==x) return x;
    return f[x]=getfather(f[x]);
}

void DFS(int F,int x,int depth) {
    H[x]=depth;
    for(int p=Head[x];p;p=Next[p]) {
        if(Node[p]==F) continue;
        Fa[Node[p]][0]=x;
        V[Node[p]][0]=D[p];
        DFS(x,Node[p],depth+1);
    }
}

int Lca(int x,int y) {
    int ans=0;
    if(H[x]<H[y]) swap(x,y);
    for(int i=MX;i>=0;i--) 
        if(H[Fa[x][i]]>=H[y]) {
            ans=max(ans,V[x][i]);
            x=Fa[x][i];
        }
    if(x==y) return ans;
    for(int i=MX;i>=0;i--) {
        if(Fa[x][i]!=Fa[y][i]) {
            ans=max(ans,V[x][i]);
            ans=max(ans,V[y][i]);
            x=Fa[x][i];
            y=Fa[y][i];
        }
    }
    ans=max(ans,V[x][0]);
    ans=max(ans,V[y][0]);
    return ans;
}

int main()
{
    scanf("%d%d%d",&n,&m,&Q);
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=1;i<=m;i++) {
        scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].d);
    }
    sort(E+1,E+m+1,cmp);
    for(int i=1;i<=m;i++) {
        int f1=getfather(E[i].u);
        int f2=getfather(E[i].v);
        if(f1!=f2) {
            f[f2]=f1;
            link(E[i].u,E[i].v,E[i].d);
            link(E[i].v,E[i].u,E[i].d);
        }
    }
    DFS(0,1,1);
    for(int k=1;k<=MX;k++) {
        for(int i=1;i<=n;i++) {
            if(!Fa[Fa[i][k-1]][k-1]) continue;
            Fa[i][k]=Fa[Fa[i][k-1]][k-1];
            V[i][k]=max(V[i][k-1],V[Fa[i][k-1]][k-1]);
        }
    }
    for(int i=1;i<=Q;i++) {
        int u,v;
        scanf("%d%d",&u,&v);
        printf("%d\n",Lca(u,v));
    }
    return 0;
}

你可能感兴趣的:(最小生成树,LCA)