ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer 最大生成树 lca

 大概就是要每两个点 只能有一条路径,并且约束,最短的边用来砌墙,那么反之的意思就是最大的边用来穿过

故最大生成树

生成以后 再用lca计算树上两点间的距离

(当然防止生成树是一条链,可以用树的重心作为根) ,然后简单的统计下树上两点的距离就行了

#include <bits/stdc++.h>
using namespace std;

const int N = 510*510*2;
int n, m, sum, fa[N];

struct node {
    int u,v,val;
    node(){}
    node(int uu,int vv,int va):u(uu),v(vv),val(va){}
}E[N]; int etot;

int Id(int x,int y) {
    return (x-1)*m+y;
}

int Find(int x) {
    return fa[x] == x ? x : fa[x]=Find(fa[x]);
}

bool join(int u,int v) {
    int fu = Find(u);
    int fv = Find(v);
    if(fu!=fv) {
        fa[fu] = fv;
        return true;
    }
    return false;
}

int tot, head[N], nex[N], son[N], dep[N], f[N][20];
void add(int u,int v) {
    nex[++tot] = head[u];
    son[tot] = v;
    head[u] = tot;
}

void addEdge(int u,int v) {
    add(u,v);
    add(v,u);
}

void dfs(int x,int fa) {
    f[x][0] = fa;
    for(int i=1; f[x][i-1]; i++) {
        f[x][i] = f[f[x][i-1]][i-1];
    }
    for(int i=head[x]; i; i=nex[i]) {
        if(son[i] != fa) {
            dep[son[i]] = dep[x] + 1;
            dfs(son[i],x);
        }
    }
}
void Lca(int u,int v) {
    if(dep[u] < dep[v])
        swap(u,v);
    int ans = dep[u]-dep[v];
    for(int i=19;i>=0;i--) {
        if(dep[u] - (1<<i) >= dep[v])
            u=f[u][i];
    }
    for(int i=19;i>=0;i--) {
        if(f[u][i] != f[v][i])
            u=f[u][i], v=f[v][i], ans+=(1<<(i+1));
    }
    if(u!=v) ans+=2;
    printf("%d\n",ans);
}

int main ()
{
    freopen("in.txt","r",stdin);
    scanf("%d %d", &n, &m);
    sum=n*m;
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=m;j++) {
            int x,y; scanf("%*s %d %*s %d", &x, &y);
            if(i < n)
                E[++etot]=node(Id(i,j), Id(i+1,j), x);
            if(j < m)
                E[++etot]=node(Id(i,j), Id(i,j+1), y);
        }
    }
    sort(E+1,E+1+etot,[](node a,node b) {
         return a.val > b.val;
    });
    for(int i=0;i<=sum;i++)
        fa[i] = i;
    for(int i=1; i<=etot; i++) {
        int u = E[i].u;
        int v = E[i].v;
        //if(join(u,v))
            //addEdge(u,v);
        int fu = Find(u), fv = Find(v);
        if(fu == fv) continue;
        fa[fu] = fa[fv];
        addEdge(u,v);
    }
    dfs(1,0);
    int Q; scanf("%d",&Q);
    while (Q--) {
        int x1,y1,x2,y2;
        scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
        Lca(Id(x1,y1),Id(x2,y2));
    }
    return 0;
}

 

posted @ 2018-09-10 14:20  Draymonder  阅读(181)  评论(0编辑  收藏  举报