ACM-ICPC 2018 徐州赛区网络预赛 J - Maze Designer

9/13/2018

题目链接:https://nanti.jisuanke.com/t/31462

题意: 在一个N*M的空地上,建墙造一个迷宫,使得迷宫的耗费最小,且迷宫中的任意两点之间只有一条路,题目保证每组数据的迷宫唯一。 输入迷宫中两个点的坐标,输出两点间的距离

思路:任意两点间只有一条路,显然是一棵树。在地图上建最大生成树,就可以使得墙的耗费最小。两点间距离就是在树上跑LCA

#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = (int)3e5 + 5;
int N,M,Q;
#define getpos(i,j) (i-1)*M + j

struct Edge
{
    int u,v,w;
    Edge(int _u=0,int _v=0,int _w=0)
    {
        u = _u;
        v = _v;
        w = _w;
    }
    bool operator<(const Edge a) const
    {
        return w > a.w;
    }
};

vector<Edge> e;
vector<int> G[maxn];
int f[maxn];
int Find(int x)
{
    return x == f[x] ? x : f[x] = Find(f[x]);
}

int deep[maxn],in[maxn],out[maxn],cnt,anc[maxn][21],dis;
void dfs(int u,int fa)
{
    in[u] = ++cnt;
    deep[u] = deep[fa] + 1;
    anc[u][0] = fa;
    for (int i = 1; i <= 20; ++i)
    {
        anc[u][i] = anc[anc[u][i-1]][i-1];
        if(!anc[u][i])
            break;
    }
    for(auto v:G[u])
    {
        if(v!=fa)
            dfs(v,u);
    }
    out[u] = cnt;
}

int lca(int a,int b)
{
    if(deep[a]>deep[b])
        swap(a,b);
    if(in[a] <= in[b] && out[b] <= out[a])
        return a;
    for(int i=20;~i;--i)
        if(deep[a] < deep[b] && deep[a] <= deep[anc[b][i]])
            b = anc[b][i];
    for(int i=20;~i;--i)
        if(anc[a][i]!=anc[b][i])
            a = anc[a][i], b = anc[b][i];
    return anc[a][0];
}

void init()
{
    cnt = 0;
    for (int i = 1; i < maxn; ++i)
    {
        f[i] = i;
    }
    deep[0] = 0;

}

int main()
{
    init();
    int u, v, w;
    char dir[2];
    scanf("%d%d",&N,&M);
    for(int i = 1;i <= N; ++i)
    {
        for (int j = 1; j <= M ; ++j)
        {
            u = getpos(i,j);
            for (int k = 0; k < 2; ++k)
            {
                scanf("%s%d",dir,&w);
                if (dir[0] == 'D')
                    v = getpos(i+1,j);
                else if (dir[0] == 'R')
                    v = getpos(i,j+1);
                else
                    continue;
                e.emplace_back(Edge(u,v,w));
            }
        }
    }
    sort(e.begin(),e.end());
    int x, y;
    for (auto i:e)
    {
        x = Find(i.u);
        y = Find(i.v);
        if(x!=y)
        {
            G[i.v].emplace_back(i.u);
            G[i.u].emplace_back(i.v);
            f[x] = y;
        }
    }
    dfs(getpos(1,1),0);
    scanf("%d",&Q);
    int x1, y1, x2, y2, L;
    while(Q--)
    {
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        u = getpos(x1,y1), v = getpos(x2,y2);
        L = lca(u,v);
        printf("%d\n",deep[u] + deep[v] - 2*deep[L]);
    }
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
Last Updated: 4/3/2022, 1:11:43 AM