3712: [PA2014]Fiolki

Time Limit: 30 Sec  Memory Limit: 128 MB
Submit: 303  Solved: 67
[Submit][Status][Discuss]

Description

化学家吉丽想要配置一种神奇的药水来拯救世界。
吉丽有n种不同的液体物质,和n个药瓶(均从1到n编号)。初始时,第i个瓶内装着g[i]克的第i种物质。吉丽需要执行一定的步骤来配置药水,第i个步骤是将第a[i]个瓶子内的所有液体倒入第b[i]个瓶子,此后第a[i]个瓶子不会再被用到。瓶子的容量可以视作是无限的。
吉丽知道某几对液体物质在一起时会发生反应产生沉淀,具体反应是1克c[i]物质和1克d[i]物质生成2克沉淀,一直进行直到某一反应物耗尽。生成的沉淀不会和任何物质反应。当有多于一对可以发生反应的物质在一起时,吉丽知道它们的反应顺序。每次倾倒完后,吉丽会等到反应结束后再执行下一步骤。
吉丽想知道配置过程中总共产生多少沉淀。

Input

第一行三个整数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]),按照反应的优先顺序给出。同一个反应不会重复出现。

Output

Sample Input

3 2 1
2 3 4
1 2
3 2
2 3

Sample Output

6

HINT

Source

鸣谢Jcvb

Solution

idea比较好的一道题,不是特别容易想到

很容易发现是树形结构,那么考虑把树建出来

这里自己想到了,但是忽略了一点,自己的想法是想如果x流进y,那么就建树边x-->y,但实际上是不可以的,正确的做法是新建一个节点X',x-->X',y-->X',然后把y的标号换为X',这样就可以了,很容易理解;(但要注意的是,这里建出的实际上是森林,可以DFS按时间戳划分)

那么题目就转化为树上的了,那么一个反应的询问,实际上就是找LCA,那么用倍增去找LCA即可

注意反应的顺序,那么可以按LCA的深度为第一关键字,id为第二关键字排序,统计答案就可以了

idea:

模型的转化,就如同SDOI2016省队集训R1Day4T3,转化到树上,就能简化问题,利用其性质得出结果

注意Code时的细节,避免手误

像如此转化成树的问题,不要总想直接转化,可以考虑加额外的点,这种思想 BZOJ3551Peaks加强版 的Kruskal重构树中有很好的体现

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-')f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define maxn 500010
long long ans;
struct EdgeNode{int next,to;}edge[maxn<<];
int head[maxn],cnt=;
int n,m,k,t,g[maxn],fa[maxn],father[maxn][],deep[maxn],dfn[maxn];
struct Node
{
int x,y,dp,id;
Node () {}
Node (int a,int b,int c,int d) {x=a;y=b;dp=c;id=d;}
bool operator < (const Node & A) const
{return dp==A.dp?id<A.id:dp>A.dp;}
}tmp[maxn];int tot;
void add(int u,int v) {cnt++;edge[cnt].next=head[u];head[u]=cnt;edge[cnt].to=v;}
void insert(int u,int v) {add(u,v);add(v,u);}
void DFS(int now,int tim)
{
dfn[now]=tim;
for (int i=; i<=; i++)
if ((<<i)<=deep[now]) father[now][i]=father[father[now][i-]][i-];
else break;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=father[now][])
{
deep[edge[i].to]=deep[now]+;
father[edge[i].to][]=now;
DFS(edge[i].to,tim);
}
}
int LCA(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
int dd=deep[x]-deep[y];
for (int i=; (<<i)<=dd; i++)
if (dd&(<<i)) x=father[x][i];
for (int i=; i>=; i--)
if (father[x][i]!=father[y][i])
x=father[x][i],y=father[y][i];
if (x==y) return x;
return father[x][];
}
int main()
{
n=read(); m=read(); k=read();
for (int i=; i<=n; i++) g[i]=read();
for (int i=; i<=n; i++) fa[i]=i;
for (int x,y,i=; i<=m; i++)
x=read(),y=read(),insert(n+i,fa[x]),insert(n+i,fa[y]),fa[y]=n+i;
for (int i=n+m; i; i--) if (!father[i][]) DFS(i,++t);
// printf("%d\n",t);
for (int x,y,i=; i<=k; i++)
{
x=read(),y=read();
if (dfn[x]==dfn[y]) tmp[++tot]=Node(x,y,deep[LCA(x,y)],i);
}
sort(tmp+,tmp+tot+);
for (int x,y,cd,i=; i<=tot; i++)
x=tmp[i].x,y=tmp[i].y,cd=min(g[x],g[y]),g[x]-=cd,g[y]-=cd,ans+=(long long)cd;
// printf("%d\n",tot);
printf("%lld",(long long)ans<<);
return ;
}

我是不会告诉你,WA成这个狗样是因为自己快速读入写错了,智障+10

【BZOJ-3712】Fiolki LCA + 倍增 (idea题)的更多相关文章

  1. [HDU 3712] Fiolki (带边权并查集+启发式合并)

    [HDU 3712] Fiolki (带边权并查集+启发式合并) 题面 化学家吉丽想要配置一种神奇的药水来拯救世界. 吉丽有n种不同的液体物质,和n个药瓶(均从1到n编号).初始时,第i个瓶内装着g[ ...

  2. 【codevs2370】小机房的树 LCA 倍增

    2370 小机房的树  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0 ...

  3. LCA倍增算法

    LCA 算法是一个技巧性很强的算法. 十分感谢月老提供的模板. 这里我实现LCA是通过倍增,其实就是二进制优化. 任何一个数都可以有2的阶数实现 例如16可以由1 2 4 8组合得到 5可以由1 2 ...

  4. 【LCA&倍增】货物运输 @upcexam5909

    时间限制: 1 Sec 内存限制: 128 MB 题目描述 在一片苍茫的大海上,有n座岛屿,岛屿与岛屿之间由桥梁连接,所有的岛屿刚好被桥梁连接成一个树形结构,即共n-1架桥梁,且从任何一座岛屿出发都能 ...

  5. SPOJ QTREE2 (LCA - 倍增 在线)

    You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, ...

  6. 洛谷 3379 最近公共祖先(LCA 倍增)

    洛谷 3379 最近公共祖先(LCA 倍增) 题意分析 裸的板子题,但是注意这题n上限50w,我用的边表,所以要开到100w才能过,一开始re了两发,发现这个问题了. 代码总览 #include &l ...

  7. POJ.1330 Nearest Common Ancestors (LCA 倍增)

    POJ.1330 Nearest Common Ancestors (LCA 倍增) 题意分析 给出一棵树,树上有n个点(n-1)条边,n-1个父子的边的关系a-b.接下来给出xy,求出xy的lca节 ...

  8. [BZOJ 2759] 一个动态树好题

    [BZOJ 2759] 一个动态树好题 题目描述 首先这是个基环树. 然后根节点一定会连出去一条非树边.通过一个环就可以解除根的答案,然后其他节点的答案就可以由根解出来. 因为要修改\(p_i\),所 ...

  9. cf1143E 倍增好题!

    一开始感觉用莫队可以搞一下,但是看了题解才发现这题其实是倍增套路题 把排列转换成nxt数组,然后倍增dp[i][j]表示第i个数后面有(1<<j)个数的最靠左的区间 然后从右往左扫一次即可 ...

随机推荐

  1. Javascript中document.execCommand()的用法

    document.execCommand()方法处理Html数据时常用语法格式如下:document.execCommand(sCommand[,交互方式, 动态参数]) 其中:sCommand为指令 ...

  2. 4817 江哥的dp题d

    4817 江哥的dp题d  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 已知1-N的排列P的LIS(最长上 ...

  3. WEBAPI 怎么保证安全

    先记录下   客户端登陆,服务端验证然后生成session,客户端每次调用接口的时候都把session带过去.服务端路由请求的时候都去验证session. 另外一种app的做法是,参数+用户名密码做s ...

  4. windows 10

    http://auPL.v4.b1.download.windowsupdate.com/c/updt/2015/07/10240.16384.150709-1700.th1_clientchina_ ...

  5. Cordova - 使用Cordova开发iOS应用实战1(配置、开发第一个应用)

    Cordova - 使用Cordova开发iOS应用实战1(配置.开发第一个应用) 现在比较流行使用 html5 开发移动应用,毕竟只要写一套html页面就可以适配各种移动设备,大大节省了跨平台应用的 ...

  6. scala 学习笔记(07) 一等公民的函数

    在scala中一切皆对象,一切皆函数,函数跟Int,String.Class等其它类型是处于同等的地位,换句话说,使用函数跟使用普通的类型一样,没什么区别,因此: 1.函数可以赋值给变量,可以当参数传 ...

  7. Theano2.1.1-基础知识之准备工作

    来源:http://deeplearning.net/software/theano/tutorial/index.html#tutorial 这里介绍的是使用theano的一些基础知识,虽然thea ...

  8. MySQL5.6 实现主从复制,读写分离,分散单台服务器压力

    闲来无事,在本地搭建几台虚拟机,准备配一个mysql读写分离的主从配置,版本选用最新版的,mysql.5.6.28 版本,本处使用源码安装(鄙人一向喜欢源码安装,因为centos中鄙人不知道yum安装 ...

  9. 分布式拒绝服务攻击 DDoS

    分布式拒绝服务(DDoS:Distributed Denial of Service)攻击指借助于客户/服务器技术,将多个计算机联合起来作为攻击平台,对一个或多个目标发动DDoS攻击,从而成倍地提高拒 ...

  10. Ubuntu修改文件关联

    * 在system setting>details中可以设置一部分文件关联,很弱很破. * 右键open with只能临时选择打开方式,并且可选的打开方式十分有限.如果是自己编的程序,在列表中没 ...