BZOJ3712: [PA2014]Fiolki
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
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; }
The deepest love I think,later than apart,I will live as you like