http://codeforces.com/gym/101889

I

先跑一遍最小生成树,把经过的边和答案记录下来

对于每个询问的边,显然如果处于MST中,答案不变

如果不在MST中,假设这条边连上了,那么就会和原本的MST形成环,删除这个环中权值最大的边就是答案

处理的时候,可以用LCA维护MST:给出边的两个节点u、v,那么u和v的LCA路径上的最大值边就是环中权值最大的边

代码:

#include <iostream>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
typedef long long ll;
const int MAX_V = 100005;
const int MAX_E = 200005;
const int MAX_N = 100005;
struct LCA_Online {
int N, M, E, root, in[MAX_N], head[MAX_N];
int f[MAX_N][30], c[MAX_N][30], depth[MAX_N];
struct Edge {
int to, next, cost;
} es[MAX_N << 2];
void addEdge(int u, int v, int w) {
es[E].to = v;
es[E].next = head[u];
es[E].cost = w;
head[u] = E++;
in[v]++;
}
void init(int N) {
this->N = N;
this->M = floor(log2(double(N)));
this->E = 0;
this->root = 0;
memset(head, -1, sizeof head);
memset(f, 0, sizeof f);
memset(c, 0, sizeof c);
memset(in, 0, sizeof in);
}
void dfs(int u) {
for (int j = 1; j <= M; j++) {
f[u][j] = f[f[u][j - 1]][j - 1];
c[u][j] = max(c[u][j - 1], c[f[u][j - 1]][j - 1]);
}
for (int i = head[u]; ~i; i = es[i].next) {
int v = es[i].to;
int w = es[i].cost;
if (v != f[u][0]) {
depth[v] = depth[u] + 1;
f[v][0] = u;
c[v][0] = w;
dfs(v);
}
}
}
void run() {
dfs(1);
}
int LCA(int u, int v) {
if (depth[u] < depth[v]) {
swap(u, v);
}
int res = 0;
int d = depth[u] - depth[v];
for (int i = 0; i <= M; i++) {
if ((1 << i) & d) {
res = max(res, c[u][i]);
u = f[u][i];
}
}
if (u == v) {
return res;
}
for (int i = M; i >= 0; i--) {
if (f[u][i] != f[v][i]) {
res = max(res, max(c[u][i], c[v][i]));
u = f[u][i];
v = f[v][i];
}
}
return max(res, max(c[u][0], c[v][0]));
}
} lca;
struct Kruskal {
struct Edge {
int from, to, cost;
bool operator< (const Edge& e) const {
return cost < e.cost;
}
} es[MAX_E];
int V, E, p[MAX_V];
void init(int V) {
this->V = V;
this->E = 0;
for (int i = 0; i < V; i++) {
p[i] = i;
}
}
void addEdge(int u, int v, int w) {
es[E].from = u;
es[E].to = v;
es[E].cost = w;
E++;
}
int find(int x) {
return x == p[x] ? x : p[x] = find(p[x]);
}
void unite(int x, int y) {
p[find(y)] = find(x);
}
ll kruskal() {
ll sum = 0;
sort(es, es + E);
for (int i = 0; i < E; i++) {
Edge &e = es[i];
if (find(e.from) != find(e.to)) {
sum += e.cost;
unite(e.from, e.to);
lca.addEdge(e.from, e.to, e.cost);
lca.addEdge(e.to, e.from, e.cost);
}
}
return sum;
}
} kru;
map<pair<int, int>, int> cost;
int main() {
int N, R, Q;
scanf("%d%d", &N, &R);
kru.init(N);
lca.init(N);
for (int i = 0, u, v, w; i < R; i++) {
scanf("%d%d%d", &u, &v, &w);
if (u > v) {
swap(u, v);
}
cost[make_pair(u, v)] = w;
//cost[make_pair(v, u)] = w;
kru.addEdge(u, v, w);
//kru.addEdge(v, u, w);
}
ll ans = kru.kruskal();
lca.run();
scanf("%d", &Q);
while (Q--) {
int u, v;
scanf("%d%d", &u, &v);
if (u > v) {
swap(u, v);
}
printf("%I64d\n", ans + cost[make_pair(u, v)] - lca.LCA(u, v));
}
}

【最小生成树+LCA】Imperial roads的更多相关文章

  1. gym 101889I Imperial roads 最小生成树+LCA

    题目传送门 题意: 给出一幅无向带权图,q次询问,每次询问都求一棵包含给出的边的最小生成树. 思路: 首先求出最小生成树(kruskal),如果查询的边在最小生成树上,肯定是直接输出最小生成树,如果不 ...

  2. bzoj3732: Network--kruskal最小生成树+LCA

    这是一道写起来比较顺手的题目 没有各种奇怪的细节,基本就是Kruskal和倍增LCA的模板.. 题目大意:对于一个无向带权图,询问两点之间一条路,使得这条路上的最长边最小,输出最小最长边的的值 那么既 ...

  3. kruskal算法求最小生成树(jungle roads的kruskal解法)

    注意: 注意数组越界问题(提交出现runtimeError代表数组越界) 刚开始提交的时候,边集中边的数目和点集中点的数目用的同一个宏定义,但是宏定义是按照点的最大数定义的,所以提交的时候出现了数组越 ...

  4. Drivers Dissatisfaction 最小生成树+LCA

    题意:给一张n个点m条边的连通图,每条边(ai,bi)有一个权值wi和费用ci, 表示这条边每降低1的权值需要ci的花费.现在一共有S费用可以用来降低某些边的权值 (可以降到负数),求图中的一棵权值和 ...

  5. [Codevs1519]过路费解题报告|最小生成树|LCA

    在某个遥远的国家里,有 n个城市.编号为 1,2,3,…,n.这个国家的政府修建了m 条双向道路,每条道路连接着两个城市.政府规定从城市 S 到城市T需要收取的过路费为所经过城市之间道路长度的最大值. ...

  6. 【BZOJ2238】Mst 最小生成树+LCA+堆

    [BZOJ2238]Mst Description 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影响,即被删掉的 ...

  7. 最小生成树:POJ1251-Jungle Roads(最小生成树的模板)

    POJ 1251 Jungle Roads >[poj原址:http://poj.org/problem?id=1251](http://poj.org/problem?id=1251) Des ...

  8. UVA - 11354Bond最小生成树,LCA寻找近期公共祖先

    看懂题目意思.他的意思是求将全部的城市走一遍,危急度最小.而且给 你两个s,t后让你求在走的时候,从s到t过程中危急度最大的值,并输出它, 然后就是怎样攻克了,这个题目能够说简单,也能够说难 通过思考 ...

  9. 最小生成树 D - Constructing Roads

    There are N villages, which are numbered from 1 to N, and you should build some roads such that ever ...

随机推荐

  1. BufferedImage缓存图片(data:image/jpg;base64,)转换base64输出与解析

    1.比如说二维码图片数据data,不想落地生成jpg文件,通过java缓存文件转换base64输出到页面展示,那么java后端处理写法参考如下: InputStream is = new ByteAr ...

  2. C# 依据鼠标坐标取网页内成员坐标.ie

    C# 根据鼠标坐标取网页内成员坐标.ie 有时候你需要后台获取ie浏览器 鼠标所在位置的元素坐标,然而你使用屏幕坐标是不可行的 所以我们需要把坐标转换成浏览器内坐标 然后再通过elementFromP ...

  3. [试玩] FMXLinux (Firemonkey for Linux) Linux 桌面开发(第三方插件)

    FMXLinux 是一个可以用来开发 Linux 桌面软件的第三方插件,它需要配合 Delphi 10.2 Toyko 官网:http://www.fmxlinux.com/ 使用方法:开启 FMX ...

  4. Delphi XE10.1 引用计数

      以往的Delphi版本,不支持接口的Weak,和UnSafe的引用,支持对象的Weak, UnSafe,而且仅在Android和Ios平台上支持. 现在Delphi XE10.1 Berlin终于 ...

  5. pomelo vscode 调试配置

    步骤 config/server.js 配置 .vscode/launch.json 配置 详细 1. 在server的配置中添加 args 参数,此参数为node开启此服务器时命令参数 " ...

  6. Field Security Profile Helper

    using System; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Messages; /// <summary> /// 安全字 ...

  7. 关于flume的filechannel的 full 问题

    事务启动以后,批量向事务Transaction的一个putList的尾部写入,putlist是一个LinkedBlockingDeque . 事务提交的时候, 把putlist中的event批量移除, ...

  8. Python学习 :异常处理

    异常处理 什么是异常处理 - python解释器检测到错误,触发异常(也允许程序员自己触发了异常) - 程序员编写特定的代码,专门用来捕捉这个异常(这段代码与程序逻辑无关,只与异常处理有关) - 如果 ...

  9. python 消息队列-rabbitMQ 和 redis介绍使用

    1.rabbitMQ 与ptyhon 进程queue 区别.进程queue 主要用户Python父子进程之间或者统一进程不同子进程.rabbit可以用户不同语言之前的相互交流,socket可以实现同样 ...

  10. 20145207 2016-2017-2 《Java程序设计》第4周学习总结

    一.继承与多态 1.继承的定义 面对对象中,子类继承父类,避免重复的行为定义,不过并非为了避免重复定义行为就使用继承,滥用而继承会导致程序维护上的问题. 程序代码重复在程序设计上就是不好的信号,多个类 ...