1. 程式人生 > >BZOJ3712: [PA2014]Fiolki

BZOJ3712: [PA2014]Fiolki

數據 ext 步驟 化學 tex oot cstring zoj can

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]),按照反應的優先順序給出。同一個反應不會重復出現。

Sample Input

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

Sample Output

6
不是很會做,想了很多數據結構都不是很資瓷 看了一發路牌:LCA考慮LCA做法 對於合並兩個瓶子,就看做一個新節點連向這兩個節點,最終會構成一棵樹 然後對於每對關系,發生的一定是兩個節點在同一顆樹裏,先後順序按照LCA的深度判定 建圖時跑了個並查集維護
代碼如下:
//MT_LI
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include
<algorithm> using namespace std; int n,m,T; struct node{ int x,y,next; }a[410000];int len,last[410000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int f[410000][21],dep[410000]; int g[210000];int bin[21]; int fa[410000]; int v[410000]; void dfs(int x,int fa) { v[x]=1; dep[x]=dep[fa]+1;f[x][0]=fa; for(int i=1;bin[i]<=dep[x];i++)f[x][i]=f[f[x][i-1]][i-1]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=fa)dfs(y,x); } } int findfa(int x) { if(fa[x]!=x)fa[x]=findfa(fa[x]); return fa[x]; } int LCA(int x,int y) { if(dep[x]<dep[y])swap(x,y); for(int i=19;i>=0;i--) if(dep[x]-bin[i]>=dep[y]) x=f[x][i]; if(x==y)return x; for(int i=19;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; } struct Q{ int x,y,dep,id; }q[510000]; typedef long long ll; bool cmp(Q a,Q b){return a.dep!=b.dep?a.dep>b.dep:a.id<b.id;} int main() { bin[0]=1; for(int i=1;i<=19;i++)bin[i]=bin[i-1]<<1; len=0;memset(last,0,sizeof(last)); scanf("%d%d%d",&n,&m,&T); for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<=n;i++)scanf("%d",&g[i]); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); int fx=findfa(x),fy=findfa(y); n++;ins(n,fx);ins(n,fy);fa[n]=n; fa[fx]=n,fa[fy]=n; } memset(v,0,sizeof(v)); for(int i=1;i<=n;i++) if(!v[i]) { int root=findfa(i); dep[root]=0;dfs(root,0); } for(int i=1;i<=T;i++) { scanf("%d%d",&q[i].x,&q[i].y); if(findfa(q[i].x)!=findfa(q[i].y)){q[i].dep=-1<<30;continue;} q[i].dep=dep[LCA(q[i].x,q[i].y)];q[i].id=i; } sort(q+1,q+1+T,cmp); ll ans=0ll; for(int i=1;q[i].dep!=-1<<30&&i<=T;i++) { int tt; ans+=2*(tt=min(g[q[i].x],g[q[i].y])); g[q[i].x]-=tt,g[q[i].y]-=tt; } printf("%lld\n",ans); return 0; }

BZOJ3712: [PA2014]Fiolki