计蒜客 徐州网络赛J.Maze Designer(最小生成树)

题目:给一个n*m的方格,每个格子中间有个权值表示加上一堵墙的代价,然后需要构成一个图是的任意两点直接有且只有一条路,给出q组询问,每次查询两点之间的最短距离。

思路:最大生成树,求lca。很裸的一道题目,唉。但是比赛时没读懂题意,以为每次查询都对应着一个图。。。。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=500*500+10;
struct node{
    int x,y;
    ll w;
}s[maxn<<2];
ll w[505][505][2];
int n,m,cnt;
bool cmp(const node &a,const node&b)
{
    return a.w>b.w;
}
vector<int>a[maxn];
int f[maxn][22],dep[maxn];
void dfs(int u,int fa)
{
    for(int i=0;i<a[u].size();i++)
    {
        int v=a[u][i];
        if(v==fa) continue;
        f[v][0]=u;
        dep[v]=dep[u]+1;
        dfs(v,u);
    }
}
int solve(int x,int y)
{
    int ans=dep[x]+dep[y];
    if(dep[x]<dep[y])
        swap(x,y);
    for(int i=20;i>=0;i--)
    {
        int k=f[x][i];
        if(dep[k]>=dep[y])
            x=k;
    }
    if(x!=y)
    {
        for(int i=20;i>=0;i--)
        {
            if(f[x][i]!=f[y][i])
            {
                x=f[x][i];
                y=f[y][i];
            }
        }
        x=f[x][0];
    }
    ans-=2*dep[x];
    return ans;
}
int fa[maxn];
int getfa(int x)
{
    return fa[x]==x?x:fa[x]=getfa(fa[x]);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            char d[3],r[3];ll x,y;
            scanf("%s%lld%s%lld",d,&x,r,&y);
            w[i][j][0]=y;
            w[i][j][1]=x;
        }
    }
    cnt=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(i!=n)
            {
                s[++cnt].x=(i-1)*m+j;
                s[cnt].y=i*m+j;
                s[cnt].w=w[i][j][1];
            }
            if(j!=m)
            {
                s[++cnt].x=(i-1)*m+j;
                s[cnt].y=(i-1)*m+j+1;
                s[cnt].w=w[i][j][0];
            }
        }
    }
    sort(s+1,s+cnt+1,cmp);
    n=n*m;
    for(int i=1;i<=n;i++)
        fa[i]=i;
    for(int i=1;i<=cnt;i++)
    {
        int x=s[i].x,y=s[i].y;
        int fx=getfa(x),fy=getfa(y);
        if(fx!=fy)
        {
            fa[fx]=fy;
            a[x].push_back(y);
            a[y].push_back(x);
        }
    }
    dep[1]=1;
    dfs(1,-1);
    for(int j=1;j<=20;j++)
    {
        for(int i=1;i<=n;i++)
            f[i][j]=f[f[i][j-1]][j-1];
    }
    int q;
    scanf("%d",&q);
    while(q--)
    {
        int x,y,xx,yy;
        scanf("%d%d%d%d",&x,&y,&xx,&yy);
        x=(x-1)*m+y;
        y=(xx-1)*m+yy;
        int ans=solve(x,y);
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dllpXFire/article/details/82561327