贴一下使用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的更多相关文章

  1. Egyptian Collegiate Programming Contest (ECPC 2015)

    题目链接:https://vjudge.net/contest/155219#overview. A题,用全排列来找出比当前这个数字字典序还大的排列有几个,然后前缀和dp即可.据说可以康拓展开来快速找 ...

  2. 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 ...

  3. 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,求每个子树中最长的边,满 ...

  4. 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree

    原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...

  5. BZOJ.3307.雨天的尾巴(dsu on tree/线段树合并)

    BZOJ 洛谷 \(dsu\ on\ tree\).(线段树合并的做法也挺显然不写了) 如果没写过\(dsu\)可以看这里. 对修改操作做一下差分放到对应点上,就成了求每个点子树内出现次数最多的颜色, ...

  6. Codeforces.741D.Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree 思路)

    题目链接 \(Description\) 给定一棵树,每条边上有一个字符(a~v).对每个节点,求它的子树中一条最长的路径,满足 路径上所有边上的字符可以重新排列成一个回文串.输出其最长长度. \(n ...

  7. 树上统计treecnt(dsu on tree 并查集 正难则反)

    题目链接 dalao们怎么都写的线段树合并啊.. dsu跑的好慢. \(Description\) 给定一棵\(n(n\leq 10^5)\)个点的树. 定义\(Tree[L,R]\)表示为了使得\( ...

  8. 【学习笔记】dsu on tree

    我也不知道为啥这要起这名,完完全全没看到并查集的影子啊…… 实际上原理就是一个树上的启发式合并. 特点是可以在$O(nlogn)$的时间复杂度内完成对无修改的子树的统计,复杂度优于莫队算法. 局限性也 ...

  9. 树上启发式合并(dsu on tree)学习笔记

    有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...

随机推荐

  1. 算法入门系列一--DP初步

    数字三角形(数塔问题) 其实动态规划本身并不是一个特定的算法,是一种用途广泛的问题求解方法,一种思想,一种手段. 1.1问题描述与状态定义 有一个有非负整数组成的三角形,第一行一个数字,下面各行除了最 ...

  2. [连载]JavaScript讲义(04)--- 函数和闭包

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamFja2ZydWVk/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA ...

  3. 《赢在用户:Web人物角色创建和应用实践指南》阅读总结

           本书针对创建人物角色的每一个步骤,包括进行定性.定量的用户研究,生成人物角色分类,使人物角色真实可信等进行了十分详细的介绍.而且,在人物角色如何指导总体商业策略.确定信息架构.内容和设计 ...

  4. Python学习 之 对内存的使用(浅拷贝和深拷贝)

    1.浅拷贝:对引用的拷贝,只拷贝父对象 cope() 深拷贝:对对象资源的拷贝 deepcope()

  5. 网络IPC:套接字之套接字描述符

    套接字是通信端点的抽象.与应用程序要使用文件描述符访问文件一样,访问套接字也需要套接字描述符.套接字描述符在UNIX系统是用文件描述符实现的.事实上,许多处理文件描述符的函数(如read和write) ...

  6. 如何在Android应用程序中使用传感器(OpenIntents开源组织SensorSimulator项目)

    原文地址http://blog.sina.com.cn/s/blog_621c16b101013ygl.html OpenIntents项目和可用资源介绍 [1].    项目介绍:OpenInten ...

  7. Mac OS 10.10 Yosemite正式版怎么升级 升级教程

    苹果在2014年10月17号凌晨一点召开了新品发布会,推出了新的 iPad.iMac 产品,以及大家一直所期盼的 Mac OS 10.10 正式版系统.个人是从 Mac OS 10.10 的第一个测试 ...

  8. QQWry.dat 数据写入

    纯真IP库 数据多,更新及时,很多同学在用,网上关于其读取的帖子也有不少(当然其中有一些是有BUG的),但却很少有关于其写入的帖子.OK,下面分享下写QQWry.dat. QQWry.dat 分三个部 ...

  9. hdu1051 Wooden Sticks

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1051 大意:求最少升序序列的个数. #include <cstdio> #include &l ...

  10. js中常用属性备忘

    . onsubmit一般用来做验证的,用来控制表单提交的. 之前使用数据提交基本上使用ajax做数据提交,在数据验证的时候,只有通过数据验证之后,才会post/get数据到对应api文件,但是这次涉及 ...