10
12
2015
0

3712: [PA2014]Fiolki

3712: [PA2014]Fiolki

Time Limit: 30 Sec  Memory Limit: 128 MB
Submit: 269  Solved: 57
[Submit][Status][Discuss]

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

Output

 

Sample Input

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

Sample Output

6

HINT

 

Source

    因为没有写>=所以倍增lca炸了一下午。。。调了两节课感觉爽爽哒。。。

    先对所有的操作建一棵树。。两种溶液混合就新建一个点把两种溶液的父亲指向他。。

    然后对所有询问中的两个点求lca。。然后按照深度排序。。然后就好了。。。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll int
using namespace std;
const ll N = 400010;
struct data{ll x,y,ans,id;} q[500010];
struct node{ll x,y,next;} e[N];
ll deep[N],fa[N][30],f[N],head[N],n,m,k,x,y,cnt,g[N],used[N];
long long sum;
ll read(){
	ll x = 0,f = 1,c = getchar();
	while (c<'0' || c>'9') {if (c=='-') f = -1;c = getchar();}
	while (c>='0' && c<='9') x = x*10+c-'0',c = getchar();
	return x*f;
}
bool cmp(data a,data b){if (a.ans==b.ans) return a.id<b.id;return a.ans>b.ans;}
void Insert(ll x,ll y){
	e[++cnt].x = x;e[cnt].y = y;
	e[cnt].next = head[x];head[x] = cnt;
}
void dfs(ll x,ll Fa){
	for (ll i=1;i<=28;i++){
		if (deep[x]<(1<<i)) break;
		fa[x][i] = fa[fa[x][i-1]][i-1];
	}
	for (ll i=head[x];i;i=e[i].next)
		if (e[i].y!=Fa){
			deep[e[i].y] = deep[x]+1;
			fa[e[i].y][0] = x;
			dfs(e[i].y,x);
		}
}
ll lca(ll x,ll y){
	if (deep[x]<deep[y]) swap(x,y);
	ll d = deep[x]-deep[y];
	for (ll i=0;i<=28;i++)
		if (d&(1<<i)) x = fa[x][i];
	for (ll i=28;i>=0;i--)
		if (fa[x][i]!=fa[y][i]) x = fa[x][i],y = fa[y][i];
	if (x==y) return x;
	else return fa[x][0];
}
ll get(ll x){return f[x]==x?x:f[x] = get(f[x]);}
int main(){
	n = read();m = read();k = read();
	for (ll i=1;i<=n;i++) g[i] = read();
	for (int i=1;i<=n+m;i++) f[i] = i;
	int tot = n;
	for (ll i=1;i<=m;i++){
		x = read();y = read();
		int fx = get(x),fy = get(y);
		used[fx] = used[fy] = 1;
		Insert(++tot,fx);Insert(tot,fy);
		f[fx] = tot;f[fy] = tot;
	}
	for (ll i=1;i<=k;i++) q[i].x = read(),q[i].y = read(),q[i].id = i;
	for (ll i=1;i<=n+m;i++) if (!used[i]) deep[i] = 1,dfs(i,-1);
	for (ll i=1;i<=k;i++){
		ll fx = get(q[i].x),fy = get(q[i].y);
		if (fx!=fy) {q[i].ans = 0;continue;}
		else q[i].ans = deep[lca(q[i].x,q[i].y)];
	}
	sort(q+1,q+1+k,cmp);
	for (ll i=1;i<=k;i++)
		if (q[i].ans!=0){
			if (g[q[i].x]<=g[q[i].y]){sum+=2ll*g[q[i].x];g[q[i].y]-=g[q[i].x];g[q[i].x] = 0;}
			else {sum+=2ll*g[q[i].y];g[q[i].x]-=g[q[i].y];g[q[i].y] = 0;}
		}
	printf("%lld",sum);
}
Category: BZOJ题解 | Tags: | Read Count: 359

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com