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

题意

一个N*M的矩形,每个格点到其邻近点的边有其权值,需要构建出一个迷宫,使得构建迷宫的边权之和最小,之后Q次查询,每次给出两点坐标,给出两点之间的最短路径

分析

可以把每个格点视作视作图的点,隔开两点的边视作图的边,则构建迷宫可以视作求其生成树,剩余的边就是组成迷宫的墙.因为要花费最小,所以使删去的墙权置最大即可,呢么就是求最大生成树即可.
然后每次查询相当于查这个最大生成树上任意两点的最短距离,到这一步就是个LCA了。

这题码量不少,还好队友给力。

#include <iostream>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <map>
#include <algorithm>
#include <queue>
#include <set>
#include <cmath>
#include <sstream>
#include <stack>
#include <fstream>
#include <ctime>
#pragma warning(disable:4996);
#define mem(sx,sy) memset(sx,sy,sizeof(sx))
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-;
const double PI = acos(-1.0);
const ll llINF = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
using namespace std;
//#define pa pair<int, int>
//const int mod = 1e9 + 7;
const int maxn = ;
const int maxq = ;
struct node {
int u, v, w, next, lca;
}; struct LCA {
node edges[maxn], ask[maxq];
int ghead[maxn], gcnt, ahead[maxn], acnt;
int anc[maxn];
int vis[maxn];
ll dist[maxn];
int fa[maxn]; void addedge(int u, int v, int w) {
edges[gcnt].v = v;
edges[gcnt].w = w;
edges[gcnt].next = ghead[u];
ghead[u] = gcnt++;
} void addask(int u, int v) {
ask[acnt].u = u;
ask[acnt].v = v;
ask[acnt].next = ahead[u];
ahead[u] = acnt++;
} void init() {
mem(vis, );
mem(ghead, -);
mem(ahead, -);
gcnt = ;
acnt = ;
} int Find(int x) {
return fa[x] == x ? x : (fa[x] = Find(fa[x]));
} void getLCA(int u, int d) {
dist[u] = d;
fa[u] = u;
vis[u] = ;
for (int i = ghead[u]; i != -; i = edges[i].next) {
int v = edges[i].v;
if (!vis[v]) {
getLCA(v, d + edges[i].w);
fa[v] = u;
anc[fa[v]] = u;
}
}
for (int i = ahead[u]; i != -; i = ask[i].next) {
int v = ask[i].v;
if (vis[v])
ask[i].lca = ask[i ^ ].lca = Find(ask[i].v);
} } }L; struct edge {
int u, v;
ll w;
bool operator<(const edge &e)const { return w>e.w; }
edge(int _u = , int _v = , ll _w = )
:u(_u), v(_v), w(_w) {}
}; struct Kruskal {
int n, m;
edge edges[maxn];
int fa[maxn];
int Find(int x) {
return fa[x] == - ? x : fa[x] = Find(fa[x]);
}
void init(int _n) {
this->n = _n;
m = ;
mem(fa, -);
} void AddEdge(int u, int v, ll dist) {
edges[m++] = edge(u, v, dist);
} ll kruskal() {
ll sum = ;
int cntnum = ;
sort(edges, edges + m);
for (int i = ; i < m; i++) {
int u = edges[i].u, v = edges[i].v;
if (Find(u) != Find(v)) {
L.addedge(u, v, );
L.addedge(v, u, );
//cout << u << " " << v << endl;
sum += edges[i].w;
fa[Find(u)] = Find(v);
if (++cntnum >= n - ) return sum;
}
}
return -;
}
}G; int main() {
int n, m;
while (~scanf("%d%d", &n, &m)) {
G.init(n*m);
L.init();
for (int i = ; i <= n; ++i) {
for (int j = ; j <= m; ++j) {
int w1, w2; char c1, c2;
scanf(" %c%d %c%d", &c1, &w1, &c2, &w2);
if (c1 == 'D') {
G.AddEdge((i - )*m + j, i*m + j, w1);
}
if (c2 == 'R') {
G.AddEdge((i - )*m + j, (i - )*m + j + , w2);
}
}
}
G.kruskal();
int q;
scanf("%d", &q);
for (int i = , x1, x2, y1, y2; i <= q; i++) {
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
int u = (x1 - )*m + y1;
int v = (x2 - )*m + y2;
L.addask(u, v);
L.addask(v, u);
}
L.getLCA(, );
for (int i = ; i < L.acnt; i += ) {
printf("%lld\n", L.dist[L.ask[i].u] + L.dist[L.ask[i].v] - * L.dist[L.ask[i].lca]);
}
}
}

ACM-ICPC 2018 徐州赛区网络预赛 J Maze Designer(最大生成树+LCA)的更多相关文章

  1. ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer (最大生成树+LCA求节点距离)

    ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer J. Maze Designer After the long vacation, the maze designer ...

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

    大概就是要每两个点 只能有一条路径,并且约束,最短的边用来砌墙,那么反之的意思就是最大的边用来穿过 故最大生成树 生成以后 再用lca计算树上两点间的距离 (当然防止生成树是一条链,可以用树的重心作为 ...

  3. ACM-ICPC 2018 徐州赛区网络预赛 J Maze Designer(最大生成树,倍增lca)

    https://nanti.jisuanke.com/t/31462 要求在一个矩形中任意选两个点都有唯一的通路,所以不会建多余的墙. 要求满足上述情况下,建墙的费用最小.理解题意后容易想到首先假设全 ...

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

    传送门:https://nanti.jisuanke.com/t/31462 本题是一个树上的问题:结点间路径问题. 给定一个有N×M个结点的网格,并给出结点间建立墙(即拆除边)的代价.花费最小的代价 ...

  5. ACM-ICPC 2018 徐州赛区网络预赛 G. Trace (思维,贪心)

    ACM-ICPC 2018 徐州赛区网络预赛 G. Trace (思维,贪心) Trace 问答问题反馈 只看题面 35.78% 1000ms 262144K There's a beach in t ...

  6. 计蒜客 1460.Ryuji doesn't want to study-树状数组 or 线段树 (ACM-ICPC 2018 徐州赛区网络预赛 H)

    H.Ryuji doesn't want to study 27.34% 1000ms 262144K   Ryuji is not a good student, and he doesn't wa ...

  7. ACM-ICPC 2018 徐州赛区网络预赛 B(dp || 博弈(未完成)

    传送门 题面: In a world where ordinary people cannot reach, a boy named "Koutarou" and a girl n ...

  8. ACM-ICPC 2018 徐州赛区网络预赛 B. BE, GE or NE

    In a world where ordinary people cannot reach, a boy named "Koutarou" and a girl named &qu ...

  9. ACM-ICPC 2018 徐州赛区网络预赛 F. Features Track

    262144K   Morgana is learning computer vision, and he likes cats, too. One day he wants to find the ...

随机推荐

  1. Java开发学习心得(一):SSM环境搭建

    目录 Java开发学习心得(一):SSM环境搭建 1 SSM框架 1.1 Spring Framework 1.2 Spring MVC Java开发学习心得(一):SSM环境搭建 有一点.NET的开 ...

  2. R语言学习——实例标识符

    > patientID<-c(1,2,3,4)> age<-c(25,34,28,52)> diabetes<-c("Type1"," ...

  3. 解决OrangePi 耳机孔没有声音

    遇到过插入耳机后没有声音,解决步骤如下: 打开终端TERMINAL(LUBUNTU按CTRL+ALT+T,MATE选SYSTERM ADMINSTRATION-MATER TERMINAL),SSH登 ...

  4. 做自己的docker镜像(基于ubuntu:16.04)

    基于ubuntu:16.04 apt-get update -y apt-get install sudo -y 换源 sudo apt-get install vim sudo vim /etc/a ...

  5. bsxfun

    By HYB bsxfun(fun,A,B)偶然间发现了这个函数,强大得不得了呀,它的作用是:对两个矩阵A和B之间的每一个元素进行指定的计算(函数fun指定):并且具有自动扩维的作用 例如,A是一个4 ...

  6. DSP到底是个什么鬼?看完你就懂了

    DSP 即数字信号处理技术, DSP 芯片即指能够实现数字信号处理技术的芯片. DSP芯片是一种快速强大的微处理器,独特之处在于它能即时处理资料. DSP 芯片的内部采用程序和数据分开的哈佛结构,具有 ...

  7. Java 控制语句

    Java 控制语句

  8. webpack4配置详解之新手上路初探

    前言 经常会有群友问起webpack.react.redux.甚至create-react-app配置等等方面的问题,有些是我也不懂的,慢慢从大家的相互交流中,也学到了不少. ​ 今天就尝试着一起来聊 ...

  9. Python之使用转义序列 \n 和 \t 跟 expandtabs 函数输出表格

    示例: text = "username\temail\tpassword\nashdfh\tfiodfh@q.com\ty567\nsdfiuh\tadfhisoj@163.com\t42 ...

  10. HashMap 与 Hashtable 的区别

    Hashtable t 小写 二者用法一致   都实现Map接口 1.HashMap 的键值可以为null,而Hashtable不允许("null" 不是 null 前者是字符串 ...