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. Orchard CRM 更新 - 同时支持 Microsoft Dynamics CRM 2011, 2013, 2015, 2016!

    本版本支持: 使用Orchard 1.8.1 系统 Dynamics CRM 2015 DLL .Net Framework 4.5.2 演示版本: http://www.orchardcrm.com ...

  2. 将函数传给webworker

    var zWorker = function (func,cb){ var node = document.createElement('script'),workerId='worker' + Da ...

  3. nfs客户端报错解决Stale file handle

    NFS故障: 场景:客户端挂载是好的.服务端磁盘满了,重新给挂了一快.客户端df -h nfs挂载消失. 客户端报错:Stale file handle 现象如下: [root@test63-spri ...

  4. [py]文件 字符串 列表特例

    文件 readlines 列表 readline 字符串 read 字符串   列表---拆分---小列表   f=file('test.log','r') for line in f.readlin ...

  5. linux addr2line 定位so库崩溃位置

    在Linux下写C/C++程序的程序员,时常与Core Dump相见.在内存越界访问,收到不能处理的信号,除零等错误出现时,我们精心或不精心写就的程序就直接一命呜呼了,Core Dump是Linux仁 ...

  6. mac 下卸载mysql的方法

    今天在mac上瞎折腾时,把mysql玩坏了,想卸载重装,却发现找不到卸载程序,百度了下,将操作步骤备份于此: cd ~/ sudo rm /usr/local/mysqlsudo rm -rf /us ...

  7. Spring Security笔记:解决CsrfFilter与Rest服务Post方式的矛盾

    基于Spring Security+Spring MVC的web应用,为了防止跨站提交攻击,通常会配置csrf,即: <http ...> ... <csrf /> </ ...

  8. ImageMagick常用指令详解

    Imagemagick常用指令 (ImageMagick--蓝天白云) (ImageMagick官网) (其他比较有价值的IM参考) (图片自动旋转的前端实现方案) convert 转换图像格式和大小 ...

  9. ubuntu-12.10-server中打开终端的方式

    ubuntu-12.10-server系统在图形界面的任务栏上找不到终端的踪影,可以使用以下两种方式调出 1.在图形界面中点击Dash Home 点击后搜索terminal即可 2.可以通过快捷键CT ...

  10. mvc5 Html.EditorFor html属性有了新变化,和以前的不同了

    @Html.EditorFor(model => model.MaxNumber, new { htmlAttributes = new { @min = "1" } })