1. 程式人生 > >Fiolki題解

Fiolki題解

algo reat pan priority i++ name 一個 stream tdi

問題 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題解