3712: [PA2014]Fiolki

Time Limit: 30 Sec  Memory Limit: 128 MB
Submit: 437  Solved: 115
[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

想法:

先看出树结构,然后分析:

一个反应最多进行一次,而且反应一定是在其LCA处反应。先不考虑中途其他反应,那么这个反应进行的时间是可以知道的。将这些反应按(反应时间,优先顺序)sort一下。模拟即可。

求反应时间就是求两个点最慢到LCA的时间,可以倍增。O(nlogn+klogn)

还有一种方法,按操作顺序,每操作一次建一个新容器用来装反应完的产物,例:x->y 这样: x->tmp y->tmp 然后y=tmp用来和后面的反应。

这样节点的深度与反应时间反相关,就可以不用倍增求,而用Tarjan求。从而O(n+k)

附上倍增代码

#include<cstdio>
#include<cmath>
#include<algorithm> typedef long long ll;
const int len(),lem(),INF(0x7fffffff);
int n,m,k,g[len+],a,b,logg;
int f[][len+],t[len+],depth[len+];
struct AB{int a,b,lca,id;}reaction[lem+];
struct Node{int nd,nx;}bot[len+];int tot,first[len+];
ll precipitation,ans; int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
bool cmp(AB A,AB B){return (A.lca<B.lca)||(A.lca==B.lca&&A.id<B.id);}
void add(int a,int b){bot[++tot]=(Node){b,first[a]};first[a]=tot;}
void swap(int &a,int &b){if(a==b)return;a^=b;b^=a;a^=b;}
template <class T>void read(T &x)
{
x=;int f=;char c=getchar();
while((c<''||c>'')&&c!='-')c=getchar(); if(c=='-')f=,c=getchar();
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
x=f?-x:x;
} void DFS(int x)
{
depth[x]++;
for(int v=first[x];v;v=bot[v].nx)
depth[bot[v].nd]=depth[x],DFS(bot[v].nd);
}
int lca(int a,int b)
{
if(depth[a]<depth[b])swap(a,b);
for(int k=depth[a]-depth[b]-,j=;k>;k>>=,j++)
if(k&)a=f[j][a];
if(f[][a]==b)return t[a];
if(depth[a]>depth[b]) a=f[][a];
for(int j=logg;f[][a]!=f[][b];j--)
if(f[j][a]!=f[j][b])a=f[j][a],b=f[j][b];
return max(t[a],t[b]);
}
int main()
{
// freopen("C.in","r",stdin);
// freopen("C.out","w",stdout);
read(n),read(m),read(k);
for(int i=;i<=n;i++)read(g[i]);
for(int i=;i<=m;i++)
{
read(a),read(b);
f[][a]=b; t[a]=i; add(b,a);
}
for(int i=;i<=n;i++)if(!f[][i])f[][i]=n+,add(n+,i),t[i]=INF;
DFS(n+);
logg=log2(n);
for(int j=;j<=logg;j++)
for(int i=;i<=n;i++)
f[j][i]=f[j-][ f[j-][i] ];
for(int i=;i<=k;i++)
{
read(a),read(b);
reaction[i].a=a;
reaction[i].b=b;
reaction[i].lca=lca(a,b);
// if(!reaction[i].lca)fprintf(stderr,"%d\n",i);
reaction[i].id=i;
}
std::sort(reaction+,reaction++k,cmp);
for(int i=;i<=k;i++)
if(reaction[i].lca!=INF)
{
precipitation=min(g[reaction[i].a],g[reaction[i].b]);
ans+=precipitation;
g[reaction[i].a]-=precipitation;
g[reaction[i].b]-=precipitation;
}else break;
printf("%lld",ans<<);
return ;
}

BZOJ 3712: [PA2014]Fiolki 倍增+想法的更多相关文章

  1. bzoj 3712: [PA2014]Fiolki

    Description 化学家吉丽想要配置一种神奇的药水来拯救世界.吉丽有n种不同的液体物质,和n个药瓶(均从1到n编号).初始时,第i个瓶内装着g[i]克的第i种物质.吉丽需要执行一定的步骤来配置药 ...

  2. 【BZOJ】3712: [PA2014]Fiolki

    http://www.lydsy.com/JudgeOnline/problem.php?id=3712 题意:n个瓶子,第i个瓶子里又g[i]克物质.m次操作,第i次操作把第a[i]个瓶子的东西全部 ...

  3. [PA2014]Fiolki

    [PA2014]Fiolki 题目大意: 有\(n(n\le2\times10^5)\)种不同的液体物质和\(n\)个容量无限的药瓶.初始时,第\(i\)个瓶内装着\(g_i\)克第\(i\)种液体. ...

  4. BZOJ3712[PA2014]Fiolki 建图+倍增lca

    居然是一道图论题 毫无思路 我们对于每一次的融合操作 $(a,b)$ 建一个新点$c$ 并向$a,b$连边 再将$b$瓶当前的位置赋成$c$ 这样子我们就可以建成一个森林 现在枚举每一种反应$M_i$ ...

  5. [bzoj3712][PA2014]Fiolki_倍增LCA

    Fiolki bzoj-3712 PA-2014 题目大意:题目链接. 注释:略. 想法: 神题! 我们建树:对于一次倾倒操作,我们弄一个新的大瓶子作为两个合并瓶子的父亲节点,与两个瓶子相连. 对于一 ...

  6. BZOJ 3721: PA2014 Final Bazarek

    3721: PA2014 Final Bazarek Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 645  Solved: 261[Submit][ ...

  7. BZOJ 3709: [PA2014]Bohater

    3709: [PA2014]Bohater Time Limit: 5 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1050  Solved: ...

  8. BZOJ 3732: Network 最小生成树 倍增

    3732: Network 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=3732 Description 给你N个点的无向图 (1 &l ...

  9. 【贪心】bzoj 3709:[PA2014]Bohater

    3709: [PA2014]Bohater Time Limit: 5 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 653  Solved:  ...

随机推荐

  1. JAVA正则表达式之 Pattern介绍

    1.简介: java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包. 它包括两个类:Pattern和Matcher. Pattern 一个Pattern是一个正则表 ...

  2. SQL中的drop,truncate和delete的区别

    (1)   DELETE语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作.TRUNCATE TABLE 则一次性地从表中删除所有的数据并不把 ...

  3. POJ 1064 Cable master (二分)

    题意:给定 n 条绳子,它们的长度分别为 ai,现在要从这些绳子中切出 m 条长度相同的绳子,求最长是多少. 析:其中就是一个二分的水题,但是有一个坑,那么就是最后输出不能四舍五入,只能向下取整. 代 ...

  4. 第一课、OpenGL绘制直线等等

    第一课.OpenGL绘制直线等等 分类: [开发技术]OpenGL 2012-01-18 14:59 5217人阅读 评论(0) 收藏 举报 buffer图形c // //  main.c //  o ...

  5. FZU - 2218 Simple String Problem(状压dp)

    Simple String Problem Recently, you have found your interest in string theory. Here is an interestin ...

  6. RabbiMQ原理与SpringBoot使用

    RabbiMQ介绍 具体代码可参考我的github:https://github.com/UniqueDong/springboot-study 一.使用场景 RabbitMQ是一个消息中间件,所以最 ...

  7. JDBC连接数据以及详细的ResultSet结果集解释

    一.数据库连接 (前面为jdbc的其他参数,文章下部分为ResultSet详解) ResultSet rs = st.executeQuery(sqlStr) 1. java的sql框架支持多种数据库 ...

  8. JS高级学习历程-11

    [继承] 在php,一个类去继承另一个类,本类实例化出来的对象,既可以调用本身类的成员,也可以调用父类的成员. 在javascript继承主要通过原型实现,构造函数继承一个对象,构造函数的实例会拥有被 ...

  9. [題解](水)luogu_P1372又是畢業季1

    被入門難度的題虐...... 作者: kkksc03 吉祥物 更新时间: 2013-07-14 19:00 在Ta的博客查看    78   By lzn 数论水题一道. 首先,若可能的最大公约数为a ...

  10. CC07:清除行列

    题目 请编写一个算法,若N阶方阵中某个元素为0,则将其所在的行与列清零. 给定一个N阶方阵int[][](C++中为vector>)mat和矩阵的阶数n,请返回完成操作后的int[][]方阵(C ...