Fiolki题解

问题 B: Fiolki

时间限制: 3 Sec  内存限制: 128 MB

题目描述

化学家吉丽想要配置一种神奇的药水来拯救世界。

吉丽有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]),按照反应的优先顺序给出。同一个反应不会重复出现。

输出

配置过程中总共产生多少沉淀。

样例输入

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

样例输出

6

 乱搞压正解,暴力出奇迹。 数据水到一定地步,当时本来期望打50分的暴力A了…… 

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<queue>
  6 #include<algorithm>
  7 #include<cmath>
  8 #define N 200005
  9 using namespace std;
 10 int n,m,t,zz2;
 11 int g[N],a[N],b[N];
 12 int f[N][2],zz;
 13 struct ro{
 14     int to,l,from;
 15     int next;
 16     bool friend operator > (ro a,ro b)
 17     {
 18         return a.l>b.l;
 19     }
 20 }road[1000005],road2[1000006];
 21 void build(int x,int y,int z){
 22     zz++;
 23     road[zz].to=y;
 24     road[zz].from=x;
 25     road[zz].l=z;
 26     road[zz].next=a[x];
 27     a[x]=zz;
 28 }
 29 void build2(int x,int y){
 30     zz2++;
 31     road2[zz2].from=x;
 32     road2[zz2].to=y;
 33     road2[zz2].next=b[x];
 34     b[x]=zz2;
 35 }
 36 int fa[N];
 37 int find(int x){
 38     if(fa[x]==x)return x;
 39     fa[x]=find(fa[x]);
 40     return fa[x];
 41 }
 42 long long hav[N];
 43 void hb(int a,int b){
 44     int x=find(a);
 45     int y=find(b);
 46     fa[x]=y;
 47     hav[y]+=hav[x];
 48     build2(y,x);
 49 }
 50 bool cle[N],cle2[N];
 51 priority_queue<ro,vector<ro>,greater<ro > > q1;
 52 void dfs(int x,int tt){
 53     //cout<<x<<endl
 54     if(!cle2[x])
 55     {
 56         for(int i=a[x];i>0;i=road[i].next)
 57         {
 58             int y=road[i].to;
 59             if(find(y)==tt)
 60             {
 61                 q1.push(road[i]);
 62             }
 63         }
 64     }
 65     bool yx=1;
 66     for(int i=b[x];i>0;i=road2[i].next)
 67     {
 68         int y=road2[i].to;
 69         if(!cle[y])
 70         {
 71             //yx=0;
 72             dfs(y,tt);
 73         }
 74         if(!cle[y])
 75         {
 76             yx=0;
 77         }
 78     }
 79     cle[x]=yx&cle2[x];
 80 }
 81 int main(){
 82     scanf("%d%d%d",&n,&m,&t);
 83     for(int i=1;i<=n;i++)
 84         scanf("%d",&g[i]);
 85     for(int i=1;i<=m;i++)
 86         scanf("%d%d",&f[i][0],&f[i][1]);
 87     for(int i=1;i<=t;i++)
 88     {
 89         int x,y;
 90         scanf("%d%d",&x,&y);
 91         build(x,y,i);
 92         build(y,x,i);
 93     }
 94     for(int i=1;i<=n;i++)
 95         fa[i]=i;
 96     for(int i=1;i<=m;i++)
 97     {
 98         int from=f[i][0],to=f[i][1];
 99         dfs(from,to);
100         while(!q1.empty())
101         {
102             ro tt=q1.top();
103             q1.pop();
104             int x=tt.from,y=tt.to;
105             int p=min(g[x],g[y]);
106             g[x]-=p;
107             g[y]-=p;
108             hav[to]+=p*2;
109             if(!g[x]) cle2[x]=1;
110             if(!g[y]) cle2[y]=1;
111         }
112         hb(from,to);
113     }
114     long long sum=0;
115     for(int i=1;i<=n;i++)
116     {
117         if(find(i)==i)
118         {
119             sum+=hav[i];
120         }
121     }
122     printf("%lld\n",sum);
123     //while(1);
124     return 0;
125 }

 
时间: 2024-11-09 03:21:39

Fiolki题解的相关文章

洛谷 P1079 Vigen&#232;re 密码 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1079 题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为 南军所广泛使用. 在密码学中,我们称需要加密的信息为明文,用 M 表示:称加密后的信息为密文,用 C 表示:而密钥是一种

8.8联考题解

今天的T1让我怀疑我是不是在做奥赛题--这考的是什么知识点啊这个,会不会用绝对值函数? Evensgn 的债务 时间限制: 1 Sec  内存限制: 128 MB 题目描述 Evensgn 有一群好朋友,他们经常互相借钱.假如说有三个好朋友A,B,C.A 欠 B 20 元,B 欠 C 20 元,总债务规模为 20+20=40 元.Evensgn 是个追求简约的人,他觉得这样的债务太繁杂了.他认为,上面的债务可以完全等价为 A 欠C20 元,B 既不欠别人,别人也不欠他.这样总债务规模就压缩到了 

POJ 2533 - Longest Ordered Subsequence(最长上升子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2533 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK)

(leetcode题解)Pascal&#39;s Triangle

Pascal's Triangle  Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,Return [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ] 题意实现一个杨辉三角. 这道题只要注意了边界条件应该很好实现出来,C++实现如下 vector<vector<int>> generate(int

2017ZZUACM省赛选拔试题部分题解----谨以纪念我这卡线滚粗的美好经历

写在前面: 其实心里有些小小的不爽又有点小小的舒畅,为啥捏?不爽当然是因为没被选拔上啦,舒畅捏则是因为没被选拔上反而让自己警醒,学长也提点很多很多."沉下去,然后一战成名"学长如是对我说,我很开心.其实这完全算不算是题解,只是我个人的一些小想法而已.而且到现在还有一题不会...让自己长点记性吧. 题目 A :聪明的田鼠 Time Limit: 1 Sec Memory Limit: 128 MB Description 田鼠MIUMIU来到了一片农田,农田可以看成是一个M*N个方格的矩

LeetCode-001题解

此题目摘自LeetCode001 Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2.

leetcode题解: Next Permutation

最近还一直在刷leetcode,当然,更多时候只是将题解写在自己的电脑上,没有分享出来.偶尔想起来的时候,就写出来. public class Solution { public void nextPermutation(int[] nums) { if(nums==null||nums.length<=1) return; nextPermutationHelp( nums,0,nums.length-1); } public void nextPermutationHelp(int []nu

HDU 5014 Number Sequence(2014 ACM/ICPC Asia Regional Xi&#39;an Online) 题解

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5014 Number Sequence Problem Description There is a special number sequence which has n+1 integers. For each number in sequence, we have two rules: ● ai ∈ [0,n] ● ai ≠ aj( i ≠ j ) For sequence a and sequ

HDU 1045 Fire Net 二分图Bipartite题解

本题可以使用DFS直接爆搜出答案,不过这样类型的题目其实是个二分图的题解. 这个二分图,难不在Hungary算法,而是难在于建图.需要挺高的抽象思维的. 建图: 1 把同一行不被X分开的格子标同一个号码,被X分开的标下一个号码,这样做是为了缩点,不需要把所有的格子都分开标号,而且可以更方便建个更加小的图. 2 同理把同一列的格子标号 3 然后判断相同一个格子的行标号和列标号是有路径的,其他不在同一个格子的都是没有路径的. 4 这样就等于以行标号和列标号作为左右顶点,构建成一个二分图了 然后使用H