版权声明:本文为博主原创文章,喜欢就点个赞吧 https://blog.csdn.net/Anxdada/article/details/82588065
传送门
题意:给定一个n*m的矩阵, 除了边界, 其他相邻的边都有一个代价, 现在我们需要在这个矩形中选择一些边封起来, 代价就是开始输入的代价, 我们要让封起来的代价和尽量的小, 并且封起来后, 矩阵中任意两点之间的最短路径是唯一的, 现在不告诉你具体是怎样封的(但是这个矩形已经进行了封墙的操作), 然后q个询问, 每次询问两个点, 他们在这个已经处理过的矩形中的最短路径是多少.
思路: 其实想到了就是个水题, 我们很明显可以将这个矩形看成一幅图, 边的代价就是输入的代价, 然后就是要让这个矩形中的任意两个点之间最短路径唯一, 实际上在图中就是一颗树啊!!! , 然后结合代价要最小, 所以我们建图后做最大生成树就是实际上矩阵的形式了, 也就是没有的边实际上就是我们要封的边. 然后询问就是询问树上两点之间的距离, 这个就可以用LCA做.. 所以实际上看通路径唯一就是做生成树, 基本上这道题就是一个水题了…. !!!
AC Code
const int maxn = 500*500 + 5;
struct node {
int to, next;
}e[maxn<<1];
struct edge {
int u, v, w;
bool operator < (const edge &_) const {
return w > _.w;
}
}s[maxn<<1];
int head[maxn], cnt;
int fa[maxn];
int n, m, k;
int up[maxn][23], dep[maxn];
void init() {
cnt = 0; Fill(head, -1);
for (int i = 1 ; i <= n*m ; i ++) fa[i] = i;
}
void add(int u, int v) {
e[cnt] = node{v, head[u]};
head[u] = cnt++;
}
int Find(int x) {
return fa[x] == x ? fa[x] : fa[x] = Find(fa[x]);
}
void work() {
for (int i = 1 ; i <= k ; i ++) {
int u = Find(s[i].u), v = Find(s[i].v);
if (u != v) {
fa[u] = v;
add(s[i].u, s[i].v);
add(s[i].v, s[i].u);
}
}
}
void dfs(int u,int fa,int d) {
dep[u] = d + 1;
for(int i = 1 ; i < 20 ; i ++) {
up[u][i] = up[up[u][i-1]][i-1];
}
for(int i = head[u] ; ~i ; i = e[i].next) {
int to = e[i].to;
if(to == fa) continue;
up[to][0] = u;
dfs(to, u, d+1);
}
}
int LCA_BZ(int u,int v) {
if(dep[u] < dep[v]) swap(u,v);
int k = dep[u] - dep[v];
for(int i = 19 ; i >= 0 ; i --) {
if((1<<i) & k) {
u = up[u][i];
}
}
if(u == v) return u;
for(int i = 19 ; i >= 0 ; i --) {
if(up[u][i] != up[v][i]){
u = up[u][i];
v = up[v][i];
}
}
return up[u][0];
}
void solve() {
scanf("%d%d", &n, &m); k = 0; init();
for (int i = 1 ; i <= n*m ; i ++) {
char op[5]; int x;
int tt = 2;
while(tt--) {
scanf("%s%d", op, &x);
if (op[0] == 'X') continue;
if (op[0] == 'R') s[++k] = edge{i, i+1, x};
else s[++k] = edge{i, i+m, x};
}
}
sort(s+1, s+1+k);
work();
dfs(1, -1, -1);
int q; scanf("%d", &q);
while(q--) {
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
int u = (x1-1) * m + y1;
int v = (x2-1) * m + y2;
printf("%d\n", dep[u] + dep[v] - 2*dep[LCA_BZ(u, v)]);
}
}