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 ...
随机推荐
- 怎样在osg中动态的设置drawable的最近最远裁剪面
// draw callback that will tweak the far clipping plane just // before rendering a drawable. s ...
- centos6.x已经安装的系统添加图形界面
yum groupinstall "X Window System" yum groupinstall GNOME Desktop Environment
- sublime php语法检查
安装sublimelinter 安装sublimelinter-php 设置sublimelinter 进入SublimeLinter文件夹改动 SublimeLinter.sublime-setti ...
- 一般php创建的文件默认不是utf-8格式的,在网上搜罗的解决办法如下:
1.PHP本身是无编码的,所有的字符串通常都视为二进制流.因此只需要输入的字符串为Utf-8即可.若字符串采用其他编码,可以使用iconv系列函数转换编码. 2.注$content = iconv(& ...
- Redis 性能测试
Redis 性能测试是通过同时执行多个命令实现的. 语法 redis 性能测试的基本命令如下: redis-benchmark [option] [option value] 实例 以下实例同时执行 ...
- c语言_帮助别人
1. /*4.找出一个二维数组中的鞍点,即该位置上的元素在该行上最大.在该列上最小,也可能没有鞍点*/ #include<stdio.h> int main() { int i,j,max ...
- 小白日记41:kali渗透测试之Web渗透-SQL手工注入(三)-猜测列名、表名、库名、字段内容,数据库写入
SQL手工注入 靶机:metasploitable(低) 1.当无权读取infomation_schema库[MySQL最重要的源数据库,必须有root权限]/拒绝union.order by语句 ...
- iOS10全新推送功能的实现
从iOS8.0开始推送功能的实现在不断改变,功能也在不断增加,iOS10又出来了一个推送插件的开发(见最后图),废话不多说直接上代码: 在开始之前需要打开一个推送开关,不然无法获取deviceToke ...
- SQL Server blocking session
select * from sys.sysprocesses where blocked>0; 96被95block住了. dbcc INPUTBUFFER(95) dbcc INPUTBUFF ...
- python(6)- json和pickle模块
这是用于序列化的两个模块: json: 用于字符串和python数据类型间进行转换 pickle: 用于python特有的类型和python的数据类型间进行转换 Json模块提供了四个功能:dumps ...