传送门:https://nanti.jisuanke.com/t/31462

本题是一个树上的问题:结点间路径问题。

给定一个有N×M个结点的网格,并给出结点间建立墙(即拆除边)的代价。花费最小的代价,使得每一对结点之间的路径唯一。给出Q次询问:每次询问一对结点的路径长度。

每一对结点之间存在路径,则图是连通的;路径唯一,则图是无环的。于是拆除边后的图是原图的一棵生成树。为使得拆除的代价尽可能小,这棵生成树应是最大生成树。通过Kruskal算法,可以求解最大生成树。

之后,即是询问树结点对的路径长度。这个问题可以通过LCA算法求解。

设结点u、v的LCA为结点k,即k=LCA(u,v),则dis(u,v)=dep[u]+dep[v]-2*dep[k]。此处通过倍增实现LCA。

参考程序如下:

#include <bits/stdc++.h>
using namespace std; #define MAX_N 300005 priority_queue<pair<int, pair<int, int> > > edge;
vector<int> adj[MAX_N]; //Union Find.
int fa[MAX_N]; void init_dset(int n)
{
for (int i = ; i < n; i++) fa[i] = i;
} int find(int u)
{
if (fa[u] == u) return u;
return fa[u] = find(fa[u]);
} void unite(int u, int v)
{
int fu = find(u), fv = find(v);
if (fu == fv) return;
fa[fu] = fv;
} bool same(int u, int v)
{
return find(u) == find(v);
} //LCA.
int pre[][MAX_N]; //Ancestor Nodes.
int dep[MAX_N]; //Depth of Nodes. void dfs(int u, int p)
{
pre[][u] = p;
for (int v : adj[u]) {
if (v != p) {
dep[v] = dep[u] + ;
dfs(v, u);
}
}
} void init_lca(int n)
{
dfs(, -);
for (int k = ; k < ; k++) {
for (int v = ; v < n; v++) {
if (pre[k][v]) pre[k + ][v] = pre[k][pre[k][v]];
}
}
} int lca(int u, int v)
{
if (dep[u] > dep[v]) swap(u, v);
for (int k = ; k < ; k++) {
if ((dep[v] - dep[u]) & ( << k)) v = pre[k][v];
}
if (u == v) return u;
for (int k = ; k >= ; k--) {
if (pre[k][u] != pre[k][v]) {
u = pre[k][u];
v = pre[k][v];
}
}
return pre[][u];
} int main(void)
{
ios::sync_with_stdio(false);
int n, m;
cin >> n >> m;
for (int i = ; i < n; i++) {
for (int j = ; j < m; j++) {
string s, t;
int a, b;
cin >> s >> a >> t >> b;
if (s[] == 'D') {
int u = i * m + j;
int v = (i + ) * m + j;
edge.push(make_pair(a, make_pair(u, v)));
}
if (t[] == 'R') {
int u = i * m + j;
int v = i * m + j + ;
edge.push(make_pair(b, make_pair(u, v)));
}
}
}
init_dset(n * m);
while (!edge.empty()) {
auto e = edge.top();
edge.pop();
int u = e.second.first;
int v = e.second.second;
if (!same(u, v)) {
unite(u, v);
adj[u].push_back(v);
adj[v].push_back(u);
}
}
init_lca(n * m);
int q;
cin >> q;
while (q--) {
int a, b, c, d;
cin >> a >> b >> c >> d;
a--; b--; c--; d--;
int u = a * m + b;
int v = c * m + d;
int k = lca(u, v);
cout << dep[u] + dep[v] - * dep[k] << endl;
}
}

最新文章

  1. 《selenium2 Java 自动化测试实战(第二版)》 更新2016.5.3
  2. quartz.net任务调度:源码及使用文档
  3. Atitit 游戏引擎---物理系统(1)------爆炸效果
  4. 30天C#基础巩固-----值类型/引用类型,泛型,空合并操作符(??),匿名方法
  5. [ERROR] Failed to execute goal org.apache.maven.plugins:maven-archetype-plugin:2.4:create (default-cli) on project standalone-pom: Unable to parse configuration of 3: mojo org.apache.maven.plugins:
  6. 关于block的一些理解
  7. Eclipse属性文件编辑器---Properties Editor
  8. algorithm@ Shortest Path in Directed Acyclic Graph (O(|V|+|E|) time)
  9. Windows Server 2012网卡Teaming模式
  10. java中super()和this()浅析
  11. Android----ListView入门知识--各种Adapter配合使用
  12. JVM垃圾收集(GC)算法
  13. 【IOI1998】Picture(扫描线+线段树)
  14. TODO springboot学习笔记
  15. vue 在全局设置cookie main.js文件
  16. ubuntu 安装cuda 9.1 pytorch 0.3.0
  17. 数据类型---列表,for循环
  18. jquery或者JavaScript调用WCF服务的方法
  19. Storm启动流程分析
  20. poj 3164

热门文章

  1. SVN导出指定版本差异文件 ***
  2. 用nginx搭建基于rtmp或者http的flv、mp4流媒体服务器
  3. Java序列化系列教程(下)
  4. JavaSwing输入对话框,点击取消抛出异常的解决方法
  5. php生成唯一订单号的方法
  6. 解决WebSocket后台报错:The WebSocket session [0] has been closed and no method (apart from close()) may be called on a closed session
  7. js截取字符串 区分中英文
  8. 60使用nanopim1plus查看HDMI显示分辨率的问题(分色排版)V1.0
  9. opencv 检测图片中圆形物体(解决乱线问题)
  10. Mysql5.7多源复制,过滤复制一段时间后增加复制一个库的实现方法