【最小生成树+LCA】Imperial roads
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的更多相关文章
- gym 101889I Imperial roads 最小生成树+LCA
题目传送门 题意: 给出一幅无向带权图,q次询问,每次询问都求一棵包含给出的边的最小生成树. 思路: 首先求出最小生成树(kruskal),如果查询的边在最小生成树上,肯定是直接输出最小生成树,如果不 ...
- bzoj3732: Network--kruskal最小生成树+LCA
这是一道写起来比较顺手的题目 没有各种奇怪的细节,基本就是Kruskal和倍增LCA的模板.. 题目大意:对于一个无向带权图,询问两点之间一条路,使得这条路上的最长边最小,输出最小最长边的的值 那么既 ...
- kruskal算法求最小生成树(jungle roads的kruskal解法)
注意: 注意数组越界问题(提交出现runtimeError代表数组越界) 刚开始提交的时候,边集中边的数目和点集中点的数目用的同一个宏定义,但是宏定义是按照点的最大数定义的,所以提交的时候出现了数组越 ...
- Drivers Dissatisfaction 最小生成树+LCA
题意:给一张n个点m条边的连通图,每条边(ai,bi)有一个权值wi和费用ci, 表示这条边每降低1的权值需要ci的花费.现在一共有S费用可以用来降低某些边的权值 (可以降到负数),求图中的一棵权值和 ...
- [Codevs1519]过路费解题报告|最小生成树|LCA
在某个遥远的国家里,有 n个城市.编号为 1,2,3,…,n.这个国家的政府修建了m 条双向道路,每条道路连接着两个城市.政府规定从城市 S 到城市T需要收取的过路费为所经过城市之间道路长度的最大值. ...
- 【BZOJ2238】Mst 最小生成树+LCA+堆
[BZOJ2238]Mst Description 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影响,即被删掉的 ...
- 最小生成树:POJ1251-Jungle Roads(最小生成树的模板)
POJ 1251 Jungle Roads >[poj原址:http://poj.org/problem?id=1251](http://poj.org/problem?id=1251) Des ...
- UVA - 11354Bond最小生成树,LCA寻找近期公共祖先
看懂题目意思.他的意思是求将全部的城市走一遍,危急度最小.而且给 你两个s,t后让你求在走的时候,从s到t过程中危急度最大的值,并输出它, 然后就是怎样攻克了,这个题目能够说简单,也能够说难 通过思考 ...
- 最小生成树 D - Constructing Roads
There are N villages, which are numbered from 1 to N, and you should build some roads such that ever ...
随机推荐
- 前端使用mobx时,变量已经修改了,为什么组件还是没变化,map类型变量,对象类型变量的值获取问题(主要矛盾发生在组件使用时)
前天我在使用一个前端多选框组件时遇到了一个问题,明明对象内的值已经修改了,但是组件显示的还是没有效果改变,以下是当时打出的log,我打印了这个对象的信息 对象内的值已经修改了但是组件还是不能及时更改, ...
- redis集群步骤(windows环境)
注:原文转自 https://blog.csdn.net/zsg88/article/details/73715947 ,仅用作为方便查阅 一 所需软件:Redis.Ruby语言运行环境.Redis的 ...
- 一条常用的 Sql
select * from table where 条件1 .... group by 字段...... Having 条件1.....Limit 0,10; 1. 根据where ...
- Delphi RAD Server 应用服务基础平台
RAD Server是一个应用服务框架平台,可快速构建和部署应用服务.RAD Server提供自动化的Delphi和C++ REST/ JSON API的 发布与管理.企业数据库集成中间件.智能物联网 ...
- Python学习手册之Python介绍、基本语法(一)
一.什么是python? python是一种高级的编程语言.它适合编写一些应用程序,比如:网站编程,脚本编程,科学计算和最近非常热门的AI(人工智能).目前,Google,腾讯,百度,阿里巴巴,豆瓣都 ...
- 检测com端口代码实现
1:scan HRESULT CDevHound::Scan(const vector<CString> &guiInfo, vector<DEV_INFO> & ...
- PTA基础编程题目集6-6求单链表结点的阶乘和(函数题)
本题要求实现一个函数,求单链表L结点的阶乘和.这里默认所有结点的值非负,且题目保证结果在int范围内. 函数接口定义: int FactorialSum( List L ); 其中单链表List的定义 ...
- C-编译器的实现
写这个编译器的目的,是为了完成编译原理课上老师布置的大作业,实际上该大作业并不是真的实现一个编译器,而我选择硬刚,是为了完成我的小愿望--手写内核,编译器和CPU.我花了整个上半学期,写完了WeiOS ...
- Python3爬虫(十八) Scrapy框架(二)
对Scrapy框架(一)的补充 Infi-chu: http://www.cnblogs.com/Infi-chu/ Scrapy优点: 提供了内置的 HTTP 缓存 ,以加速本地开发 . ...
- 20155327 2016-2017-3 《Java程序设计》第4周学习总结
20155327 2016-2017-3 <Java程序设计>第4周学习总结 教材学习内容总结 一. 理解封装.继承.多态的关系 封装:把客观事物封装成抽象的类,并且类可以把自己的数据和方 ...