BZOJ3712[PA2014]Fiolki——并查集重构树
题目描述
化学家吉丽想要配置一种神奇的药水来拯救世界。
吉丽有n种不同的液体物质,和n个药瓶(均从1到n编号)。初始时,第i个瓶内装着g[i]克的第i种物质。吉丽需要执行一定的步骤来配置药水,第i个步骤是将第a[i]个瓶子内的所有液体倒入第b[i]个瓶子,此后第a[i]个瓶子不会再被用到。瓶子的容量可以视作是无限的。
吉丽知道某几对液体物质在一起时会发生反应产生沉淀,具体反应是1克c[i]物质和1克d[i]物质生成2克沉淀,一直进行直到某一反应物耗尽。生成的沉淀不会和任何物质反应。当有多于一对可以发生反应的物质在一起时,吉丽知道它们的反应顺序。每次倾倒完后,吉丽会等到反应结束后再执行下一步骤。
吉丽想知道配置过程中总共产生多少沉淀。
输入
第一行三个整数n,m,k(0<=m<n<=200000,0<=k<=500000),分别表示药瓶的个数(即物质的种数),操作步数,可以发生的反应数量。
第二行有n个整数g[1],g[2],…,g[n](1<=g[i]<=10^9),表示初始时每个瓶内物质的质量。
接下来m行,每行两个整数a[i],b[i](1<=a[i],b[i]<=n,a[i]≠b[i]),表示第i个步骤。保证a[i]在以后的步骤中不再出现。
接下来k行,每行是一对可以发生反应的物质c[i],d[i](1<=c[i],d[i]<=n,c[i]≠d[i]),按照反应的优先顺序给出。同一个反应不会重复出现。
输出
样例输入
2 3 4
1 2
3 2
2 3
样例输出
- #include<set>
- #include<map>
- #include<cmath>
- #include<stack>
- #include<queue>
- #include<vector>
- #include<bitset>
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #define ll long long
- using namespace std;
- int n,m,k;
- int g[200010];
- int fa[400010];
- int vis[400010];
- ll ans;
- int f[400010][20];
- int d[400010];
- int cnt;
- int tot;
- int ls[400010];
- int rs[400010];
- struct miku
- {
- int dep;
- int pos;
- int x,y;
- }a[500010];
- int x,y;
- int find(int x)
- {
- if(fa[x]==x)
- {
- return x;
- }
- return fa[x]=find(fa[x]);
- }
- bool cmp(miku a,miku b)
- {
- if(a.dep!=b.dep)
- {
- return a.dep>b.dep;
- }
- return a.pos<b.pos;
- }
- void dfs(int x)
- {
- d[x]=d[f[x][0]]+1;
- for(int i=1;i<=18;i++)
- {
- f[x][i]=f[f[x][i-1]][i-1];
- }
- if(ls[x])
- {
- dfs(ls[x]);
- }
- if(rs[x])
- {
- dfs(rs[x]);
- }
- }
- int lca(int x,int y)
- {
- if(d[x]<d[y])
- {
- swap(x,y);
- }
- int dep=d[x]-d[y];
- for(int i=0;i<=18;i++)
- {
- if((dep&(1<<i)))
- {
- x=f[x][i];
- }
- }
- if(x==y)
- {
- return x;
- }
- for(int i=18;i>=0;i--)
- {
- if(f[x][i]!=f[y][i])
- {
- x=f[x][i];
- y=f[y][i];
- }
- }
- return f[x][0];
- }
- int main()
- {
- scanf("%d%d%d",&n,&m,&k);
- for(int i=1;i<=n;i++)
- {
- scanf("%d",&g[i]);
- }
- for(int i=1;i<=2*n;i++)
- {
- fa[i]=i;
- }
- cnt=n;
- for(int i=1;i<=m;i++)
- {
- scanf("%d%d",&x,&y);
- int fx=find(x);
- int fy=find(y);
- cnt++;
- f[fx][0]=cnt;
- f[fy][0]=cnt;
- fa[fx]=cnt;
- fa[fy]=cnt;
- ls[cnt]=fx;
- rs[cnt]=fy;
- }
- for(int i=1;i<=n;i++)
- {
- int rt=find(i);
- if(!vis[rt])
- {
- vis[rt]=1;
- dfs(rt);
- }
- }
- for(int i=1;i<=k;i++)
- {
- scanf("%d%d",&x,&y);
- if(find(x)==find(y))
- {
- a[++tot].dep=d[lca(x,y)];
- a[tot].pos=i;
- a[tot].x=x;
- a[tot].y=y;
- }
- }
- sort(a+1,a+1+tot,cmp);
- for(int i=1;i<=tot;i++)
- {
- int s=g[a[i].x];
- int t=g[a[i].y];
- if(s>t)
- {
- swap(s,t);
- }
- ans+=2ll*s;
- g[a[i].x]-=s;
- g[a[i].y]-=s;
- }
- printf("%lld",ans);
- }
BZOJ3712[PA2014]Fiolki——并查集重构树的更多相关文章
- 【BZOJ3712】Fiolki(并查集重构树)
[BZOJ3712]Fiolki(并查集重构树) 题面 BZOJ 题解 很神仙的题目. 我们发现所有的合并关系构成了一棵树. 那么两种不同的东西如果产生反应,一定在两个联通块恰好联通的时候反应. 那么 ...
- [学习笔记]kruskal重构树 && 并查集重构树
Kruskal 重构树 [您有新的未分配科技点][BZOJ3545&BZOJ3551]克鲁斯卡尔重构树 kruskal是一个性质优秀的算法 加入的边是越来越劣的 科学家们借这个特点尝试搞一点事 ...
- [bzoj3712][PA2014]Fiolki
description 题面 data range \[ 0\le m<n\le 200000,0\le k\le 500000\] solution 之前本人一直煞笔地思考暴力是否可行 考虑按 ...
- BZOJ3712[PA2014]Fiolki 建图+倍增lca
居然是一道图论题 毫无思路 我们对于每一次的融合操作 $(a,b)$ 建一个新点$c$ 并向$a,b$连边 再将$b$瓶当前的位置赋成$c$ 这样子我们就可以建成一个森林 现在枚举每一种反应$M_i$ ...
- [note]克鲁斯卡尔重构树
克鲁斯卡尔重构树 又叫并查集重构树 大概在NOI2018之前还是黑科技 现在?烂大街了 主要是针对图上的对边有限制的一类问题 比如每次询问一个点u不能经过边权大于w的边能走到的第k大点权是多少 也就是 ...
- [BZOJ3712]Fiolki 重构树(并查集)
3712: [PA2014]Fiolki Time Limit: 30 Sec Memory Limit: 128 MB Description 化学家吉丽想要配置一种神奇的药水来拯救世界.吉丽有n ...
- NOI2018Day1T1 归程 并查集 kruskal kruskal重构树 倍增表 Dijkstra
原文链接https://www.cnblogs.com/zhouzhendong/p/NOI2018Day1T1.html 题目传送门 - 洛谷P4768 题意 给定一个无向连通图,有 $n$ 个点 ...
- [NOI2018]归程(可持久化并查集,Kruskal重构树)
解法一: 1.首先想到离线做法:将边和询问从大到小排序,并查集维护连通块以及每个连通块中所有点到1号点的最短距离.$O(n\log n)$ 配合暴力等可以拿到75分. 2.很容易想到在线做法,使用可持 ...
- CF1253F Cheap Robot(神奇思路,图论,最短路,最小生成树/Kruskal 重构树/并查集)
神仙题. 先考虑平方级别的暴力怎么做. 明显答案有单调性,先二分 \(c\). 先最短路预处理 \(dis_u\) 表示 \(u\) 到离它最近的充电站的距离(一开始把 \(1\) 到 \(k\) 全 ...
随机推荐
- 利用 ProtoThreads实现Arduino多线程处理(1)
转载请注明:@小五义http://www.cnblogs.com/xiaowuyiQQ群:64770604 这几天和群里小V同学讨论一个项目时,偶然发现了 ProtoThreads,简称PT,用其来实 ...
- 覆写equals方法为什么需要覆写hashCode方法
覆写equals方法必须覆写hashCode方法,是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢? void test() { // Person类的实例作为Map的k ...
- Ionic Contoller类与Service类分开需要注意的问题
看了别人的项目把Controller类和Service类都写在了app.js文件里面,这不符合我的风格,想把他们分开成单独的文件,确遇见以下错误提示: ionic.bundle.min.js:133 ...
- LInq之Take Skip TakeWhile SkipWhile Reverse Union Concat 用法
废话不多说,直接上代码,代码有注释!自行运行测试! class Program { static void Main(string[] args) { string[] names = { " ...
- 51Nod 1705 七星剑
一道很新颖的概率DP,我看数据范围还以为是有指数级别的复杂度的呢 记得有人说期望要倒着推,但放在这道题上,就咕咕了吧. 我们考虑正着概率DP,设\(fi\)表示将剑升到\(i\)颗星花费的期望,这样我 ...
- Python中 and or 运算顺序详解 --- 短路逻辑
核心思想 表达式从左至右运算,若 or 的左侧逻辑值为 True ,则短路 or 后所有的表达式(不管是 and 还是 or),直接输出 or 左侧表达式 . 表达式从左至右运算,若 and 的左侧逻 ...
- python基础学习笔记(十)
魔法方法.属性 ------------------------ 准备工作 为了确保类是新型类,应该把 _metaclass_=type 入到你的模块的最开始. class NewType(Objec ...
- [个人博客作业Week7]软件工程团队项目感想与反思
在阅读了推荐阅读的材料之后,我想了很多东西.最终还是决定,以团队项目的经历为主线,叙述我关于软件工程的一些思考与体会. 凤凰涅槃,浴火重生 如果要我来概况这几周团队项目的经历的话,那么句话是我所能想到 ...
- 【实践报告】Linux实践四
Linux内核分析 实践四——ELF文件格式分析 一.概述 1.ELF全称Executable and Linkable Format,可执行连接格式,ELF格式的文件用于存储Linux程序.ELF文 ...
- 《面向对象程序设计》c++第五次作业___calculator plus plus
c++第五次作业 Calculator plusplus 代码传送门 PS:这次作业仍然orz感谢一位同学与一位学长的windows帮助,同时再次吐槽作业对Mac系统用户的不友好.(没朋友千万别用Ma ...