dsu + lca
贴一下使用dsu和lca的代码,dsu的代码很简单,可以马上写出来,但是lca的代码就不熟练了。这里lca的计算还是用了dfs的访问时间标记,我想起来割边, 割点的判断, dfu[u], low[u],的的使用,还有lca的离线算法,tarjan算法,然后又查到了求强连通分量的算法,也是使用访问时间标记,这些算法,有时间好好整理一下。dfs判断回路。等等。想起来再补充。
#include<bits/stdc++.h>
#define pb push_back
#define FOR(i, n) for (int i = 0; i < (int)n; ++i)
#define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl
typedef long long ll;
using namespace std;
typedef pair<int, int> pii;
const int maxn = 2e5 + ;
const int inf = 1e9 + ;
int n, m;
int w[maxn], c[maxn], a[maxn], b[maxn];
// dsu disjoint set union //find and union
int sz[maxn], p[maxn];
void init() {
for (int i = ; i <= n; i++) {
sz[i] = ; p[i] = i;
}
}
int get(int x) {
if(x == p[x]) return x;
return p[x] = get(p[x]);
}
bool unite(int x, int y) {
x = get(x); y = get(y);
if(x == y) return ;
if(sz[x] > sz[y]) swap(x, y);
sz[y] += sz[x];
p[x] = y;
return ;
} struct node {
int to, idx, w;
node(int to, int idx, int w) : to(to), idx(idx), w(w) {}
}; vector<node> g[maxn];
int depth[maxn];
bool used[maxn];
pii fmaxi[maxn][];
int tin[maxn], tout[maxn], timer;
int fup[maxn][];
void dfs(int v, int p, int wup, int eidx, int dep) {
tin[v] = ++timer;
fup[v][] = p;
fmaxi[v][] = {wup, eidx};
depth[v] = dep;
for (int i = ; i < ; i++) {
fup[v][i] = fup[fup[v][i - ] ][i - ];
fmaxi[v][i] = max(fmaxi[v][i - ], fmaxi[fup[v][i - ] ][i - ]);
}
for (auto it : g[v]) {
int to = it.to;
int idx = it.idx;
int w = it.w;
if(to == p) continue;
dfs(to, v, w, idx, dep + );
}
tout[v] = ++timer;
} bool isAncestor(int x, int y) {
return tin[x] <= tin[y] && tout[x] >= tout[y];
}
int lca(int x, int y) {
if(isAncestor(x, y)) return x;
if(isAncestor(y, x)) return y;
for (int i = - ; i >= ; i--) {
if(!isAncestor(fup[x][i], y)) x = fup[x][i];
}
return fup[x][];
}
pii getfmax1(int x, int p) {
int len = depth[x] - depth[p];
pii res = {-inf, -inf};
for (int i = - ; i >= ; i--) {
if((len >> i) & ) {
len ^= ( << i);
res = max(res, fmaxi[x][i]);
x = fup[x][i];
}
}
return res;
}
pii getfmax(int x, int y) {
int z = lca(x, y);
return max(getfmax1(x, z), getfmax1(y, z));
}
int S;
ll sum;
int perm[maxn];
void solve() {
cin >> n >> m;
init();
for (int i = ; i <= m; i++) cin >> w[i];
for (int i = ; i <= m; i++) cin >> c[i];
for (int i = ; i <= m; i++) cin >> a[i] >> b[i];
cin >> S;
for (int i = ; i <= m; i++)
perm[i] = i;
sort(perm + , perm + m + , [](int i, int j) {return w[i] < w[j];});
vector<int> e;
for (int j = ; j <= m; j++) {
int i = perm[j];
if(unite(a[i], b[i])) {
e.pb(i);
sum += w[i];
}
}
//cout << sum << endl;
assert((int)e.size() == n - );
for (int idx : e) {
g[a[idx] ].pb({b[idx], idx, w[idx] });
g[b[idx] ].pb({a[idx], idx, w[idx] });
}
dfs(, , -inf, -inf, );
pair<ll, pii> best = {(ll)1e18, {-, -}};
for (int idx = ; idx <= m; idx++) {
pii z = getfmax(a[idx], b[idx]);
ll nsum = sum - z.first + w[idx] - (S / c[idx]);
pair<ll, pii> cur = {nsum, {z.second, idx} };
best = min(best, cur);
}
assert(best.second.first != -);
cout << best.first << endl;
for (int idx : e) {
used[idx] = ;
}
used[best.second.first] = ;
used[best.second.second] = ;
for (int i = ; i <= m; i++) {
if(used[i]) {
cout << i << " ";
int ww = w[i];
if(i == best.second.second)
ww -= S / c[i];
cout << ww << endl;
}
} } int main() {
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
solve();
return ;
} void dfs2(int x, int lt) {
fup[x][] = lt;
for (auto it : g[x]) {
int to = it.to;
int idx = it.idx;
if(to == lt) continue;
fmaxi[to][] = {w[idx], idx};
depth[to] = depth[x] + ;
dfs2(to, x);
}
}
void build(int root) {
dfs2(, );
for (int i = ; i <= ; i++) {
for (int x = ; x <= n; x++) {
fup[x][i] = fup[fup[x][i - ] ][i - ];
fmaxi[x][i] = max(fmaxi[fup[x][i - ] ][i - ], fmaxi[x][i - ] ); }
}
}
int adv(int x, int v, pii & ret) {
for (int i = ; ( << i) <= v; i++) {
if((v >> i) & ) {
ret = max(ret, fmaxi[x][i]);
x = fup[x][i];
}
}
return x;
}
pii lca2(int x, int y) {
pii ret = {-, -};
if(depth[x] > depth[y]) x = adv(x, depth[x] - depth[y], ret);
else y = adv(y, depth[y] - depth[x], ret);
if(x == y) return ret;
for (int i = ; i >= ; i--) {
if(fup[x][i] != fup[y][i]) {
ret = max(ret, fmaxi[x][i]);
ret = max(ret, fmaxi[y][i]);
x = fup[x][i];
y = fup[y][i];
}
}
ret = max(ret, fmaxi[x][]);
ret = max(ret, fmaxi[y][]);
return ret;
}
dsu + lca的更多相关文章
- Egyptian Collegiate Programming Contest (ECPC 2015)
题目链接:https://vjudge.net/contest/155219#overview. A题,用全排列来找出比当前这个数字字典序还大的排列有几个,然后前缀和dp即可.据说可以康拓展开来快速找 ...
- HDU 5458 Stability(双连通分量+LCA+并查集+树状数组)(2015 ACM/ICPC Asia Regional Shenyang Online)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 Problem Description Given an undirected connecte ...
- CF 741D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths [dsu on tree 类似点分治]
D. Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths CF741D 题意: 一棵有根树,边上有字母a~v,求每个子树中最长的边,满 ...
- 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree
原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...
- BZOJ.3307.雨天的尾巴(dsu on tree/线段树合并)
BZOJ 洛谷 \(dsu\ on\ tree\).(线段树合并的做法也挺显然不写了) 如果没写过\(dsu\)可以看这里. 对修改操作做一下差分放到对应点上,就成了求每个点子树内出现次数最多的颜色, ...
- Codeforces.741D.Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree 思路)
题目链接 \(Description\) 给定一棵树,每条边上有一个字符(a~v).对每个节点,求它的子树中一条最长的路径,满足 路径上所有边上的字符可以重新排列成一个回文串.输出其最长长度. \(n ...
- 树上统计treecnt(dsu on tree 并查集 正难则反)
题目链接 dalao们怎么都写的线段树合并啊.. dsu跑的好慢. \(Description\) 给定一棵\(n(n\leq 10^5)\)个点的树. 定义\(Tree[L,R]\)表示为了使得\( ...
- 【学习笔记】dsu on tree
我也不知道为啥这要起这名,完完全全没看到并查集的影子啊…… 实际上原理就是一个树上的启发式合并. 特点是可以在$O(nlogn)$的时间复杂度内完成对无修改的子树的统计,复杂度优于莫队算法. 局限性也 ...
- 树上启发式合并(dsu on tree)学习笔记
有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...
随机推荐
- 让你的PHP程序真正的实现多线程(PHP多线程类)(转)
通过WEB服务器来实现PHP多线程功能. 当然,对多线程有深入理解的人都知道通过WEB服务器实现的多线程只能模仿多线程的一些效果,并不是真正意义上的多线程. 但不管怎么样,它还是能满足我们的一些需要的 ...
- oc-02-NSLog使用
#import <Foundation/Foundation.h> /* NSLog() : C语言中的 printf的增强版 作用: 向控制台输出打印数据. 增强的地方 : 打印时间 , ...
- MySQL · BUG分析 · Rename table 死锁分析
http://mysql.taobao.org/monthly/2016/03/06/ 背景 InnoDB buffer pool中的page管理牵涉到两个链表,一个是lru链表,一个是flush 脏 ...
- [原创]如何写好SqlHelper 之终章
精简的美丽...... 标题有点大.但是,我觉得99%的接近了. 好了,下面我们来说说一个SqlHelper为了适应各种不同的业务需要,它应该具备哪些基本要素. 第一点.可控的事务. 事务是数据库操作 ...
- JavaScript触摸与手势事件
JavaScript触摸与手势事件 发表于 2012-12-10 由 admin iOS版Safari为了向开发人员传达一些特殊信息,新增了一些专有事件.因为iOS设备既没有鼠标也没有键盘,所以在为移 ...
- Spark之路 --- Scala IDE Maven配置(使用开源中国的Maven库)和使用
为什么要使用Maven 摘自百度百科的介绍 Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具.Maven 除了以程序构建能力为特色之外,还提 ...
- UITableView优化技巧
UITableView的简单认识 UITableView最核心的思想就是UITableViewCell的重用机制.简单的理解就是:UITableView只会创建一屏幕(或一屏幕多一点)的UITable ...
- Java中的文件操作
在使用计算机编程中,常常会用到对于文件的操作,以下是我对于Java中文件的相关内容学习之后的一个总结和在学习过程中遇到的一些问题. 一.什么是文件 对于文件进行操作,首先我们要知道什么是文件.在此之前 ...
- 查看Oracle执行计划的几种方法
查看Oracle执行计划的几种方法 一.通过PL/SQL Dev工具 1.直接File->New->Explain Plan Window,在窗口中执行sql可以查看计划结果.其中,Cos ...
- OPENSSL安装 以及使用openssl中的AES加密和解密
OPENSSL安装:(VS) 1:第一步和所有的软件安装一样. 2:将OPENSSL中INLUCDE 和 LIB 分别拷贝到VS中VC的INLUCDE 和LIB目录下(我的机器上的目录是:C:\Pro ...