Maze Designer 计蒜客

https://nanti.jisuanke.com/t/31462

题目说两点之间路径唯一 那就是一棵树 又因为树的补图权值之和要最小 那其实就是求一个最大生成树

然后每次查询求个lca即可

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

struct node1
{
    int u;
    int v;
    ll w;
};

struct node2
{
    int v;
    int next;
};

node1 pre[500010];
node2 edge[500010];
int dp[250010][20];
int first[250010],f[250010],deep[250010];
int n,m,q,tot,num;

bool cmp(node1 n1,node1 n2)
{
    return n1.w>n2.w;
}

void addedge(int u,int v)
{
    edge[num].v=v;
    edge[num].next=first[u];
    first[u]=num++;
}

int getf(int p)
{
    if(f[p]==p) return p;
    else
    {
        f[p]=getf(f[p]);
        return f[p];
    }
}

bool unite(int u,int v)
{
    int fu,fv;
    fu=getf(u);
    fv=getf(v);
    if(fu!=fv)
    {
        f[fv]=fu;
        return true;
    }
    else return false;
}

void dfs(int cur,int fa)
{
    int i,v;
    for(i=first[cur];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        if(v!=fa)
        {
            dp[v][0]=cur;
            deep[v]=deep[cur]+1;
            dfs(v,cur);
        }
    }
    return;
}

void solve()
{
    int i,j;
    dp[1][0]=0;
    deep[1]=1;
    dfs(1,0);
    for(j=1;(1<<j)<=n*m;j++)
    {
        for(i=1;i<=n*m;i++)
        {
            dp[i][j]=dp[dp[i][j-1]][j-1];
        }
    }
    return;
}

int getlca(int u,int v)
{
    int i;
    if(deep[u]<deep[v]) swap(u,v);
    for(i=log2(n*m);i>=0;i--)
    {
        if(deep[dp[u][i]]>=deep[v])
        {
            u=dp[u][i];
        }
    }
    if(u==v) return u;
    for(i=log2(n*m);i>=0;i--)
    {
        if(dp[u][i]!=dp[v][i])
        {
            u=dp[u][i];
            v=dp[v][i];
        }
    }
    return dp[u][0];
}

int main()
{
    ll w1,w2;
    int i,j,cnt,u,v,lca;
    char ch1[10],ch2[10];
    scanf("%d%d",&n,&m);
    tot=0;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            scanf("%s%lld%s%lld",ch1,&w1,ch2,&w2);
            if(ch1[0]=='D')
            {
                tot++;
                pre[tot].u=(i-1)*m+j,pre[tot].v=i*m+j,pre[tot].w=w1;
            }
            if(ch2[0]=='R')
            {
                tot++;
                pre[tot].u=(i-1)*m+j,pre[tot].v=(i-1)*m+j+1,pre[tot].w=w2;
            }
        }
    }
    sort(pre+1,pre+tot+1,cmp);
    memset(first,-1,sizeof(first));
    for(i=1;i<=n*m;i++) f[i]=i;
    num=0,cnt=0;
    for(i=1;i<=tot;i++)
    {
        if(unite(pre[i].u,pre[i].v))
        {
            addedge(pre[i].u,pre[i].v);
            addedge(pre[i].v,pre[i].u);
            cnt++;
            if(cnt==n*m-1) break;
        }
    }
    solve();
    scanf("%d",&q);
    while(q--)
    {
        scanf("%d%d",&i,&j);
        u=(i-1)*m+j;
        scanf("%d%d",&i,&j);
        v=(i-1)*m+j;
        lca=getlca(u,v);
        printf("%d\n",deep[u]+deep[v]-2*deep[lca]);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/82561199
今日推荐