Fiolki题解

Posted Hzoi_joker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
View Code

 

 




以上是关于Fiolki题解的主要内容,如果未能解决你的问题,请参考以下文章

[bzoj3712][PA2014]Fiolki

BZOJ-3712Fiolki LCA + 倍增 (idea题)

[BZOJ3712]Fiolki 重构树(并查集)

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

bzoj 3712: [PA2014]Fiolki

BZOJ:3712: [PA2014]Fiolki