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 ...
随机推荐
- delphi SpeedButtonDown
的属性 的事件 的方法 设置SpeedButton的Down的属性 AllowAllUp属性 当有多个SpeedButton时 让有2个按钮都能处于按下状态 设置它的GroupIndex ...
- C# Func<>托付
曾经我们为了可以调用一个方法.必须比照这种方法定义一个对应的delegate. 原先我们定义delegate // 托付声明 -- 定义一个签名: delegate double MathAction ...
- android4.0蓝牙使能的详细解析
本文详细分析了android4.0 中蓝牙使能的过程,相比较android2.3,4.0中的蓝牙最大的差别在于UI上on/off的伪开关.在android4.0中加入了 adapter的状态机.所谓的 ...
- online ddl 跟踪
| >mysql_prepare_alter_table T@4 : | | | | | | <mysql_prepare_alter_table 7368 T@4 : | | | | | ...
- VRP相关知识整理
一.扩展问题分类: ★ the capacitated vehicle routing problem (CVRP) , 即classical VRP ★ the vehicle routing pr ...
- Python学习 之 对内存的使用(浅拷贝和深拷贝)
1.浅拷贝:对引用的拷贝,只拷贝父对象 cope() 深拷贝:对对象资源的拷贝 deepcope()
- LeetCode: Reverse Words in a String:Evaluate Reverse Polish Notation
LeetCode: Reverse Words in a String:Evaluate Reverse Polish Notation Evaluate the value of an arithm ...
- Google搜索语法
原文:http://www.jianshu.com/p/37fe4f1381ef 前言 之前听过一个笑话,有人打开浏览器,输入www.baidu.com, 然后搜索框输入Google,查询google ...
- hadoop实例---多表关联
多表关联和单表关联类似,它也是通过对原始数据进行一定的处理,从其中挖掘出关心的信息.如下 输入的是两个文件,一个代表工厂表,包含工厂名列和地址编号列:另一个代表地址表,包含地址名列和地址编号列.要求从 ...
- 解决iphone横屏时字体变大问题或者内容大小不一样等
在样式表中增加: @media screen and (max-device-width: 320px){body{-webkit-text-size-adjust:none}} @media scr ...