[bzoj3712][PA2014]Fiolki

description

题面

data range

\[0\le m<n\le 200000,0\le k\le 500000 \]

solution

之前本人一直煞笔地思考暴力是否可行

考虑按照操作关系直接构树,之后按照每个反应中两点在树上的\(lca\)深度排序

最后依次考虑每个反应即可

虽然说建出来的也是个\(Kruskal\)重构树

code

没有按质合并的并查集都能过

#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<ctime>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define FILE "a"
#define mp make_pair
#define pb push_back
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const dd eps=1e-10;
const int mod=1e9+7;
const int N=400010;
const int M=500010;
const dd pi=acos(-1);
const int inf=2147483645;
const ll INF=1e18+1;
const ll P=100000;
il ll read(){
	RG ll data=0,w=1;RG char ch=getchar();
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
	return data*w;
}

il void file(){
	srand(time(NULL)+rand());
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
}

int num,n,m,k,g[N],t;ll ans;
int fa[N],f[20][N];
int find(int x){return fa[x]?fa[x]=find(fa[x]):x;}
int dep[N],RT;
int head[N],nxt[N],to[N],cnt;
il void add(int u,int v){
	to[++cnt]=v;
	nxt[cnt]=head[u];
	head[u]=cnt;
}
void dfs(int u,int ff){
	f[0][u]=ff;dep[u]=dep[ff]+1;
	for(RG int i=1;f[i-1][f[i-1][u]];i++)f[i][u]=f[i-1][f[i-1][u]];
	for(RG int i=head[u];i;i=nxt[i]){
		RG int v=to[i];dfs(v,u);
	}
}
struct edge{int u,v,id,d;}E[M];
bool cmp(edge x,edge y){if(x.d==y.d)return x.id<y.id;return x.d>y.d;}
il int lca(int u,int v){
	if(dep[u]<dep[v])swap(u,v);
	RG int d=dep[u]-dep[v];
	for(RG int i=19;~i;i--)if(d&(1<<i))u=f[i][u];
	if(u==v)return u;
	for(RG int i=19;~i;i--)
		if(f[i][u]!=f[i][v])u=f[i][u],v=f[i][v];
	if(u==v)return u;
	return f[0][u];
}

int main()
{
	num=n=read();m=read();k=read();
	for(RG int i=1;i<=n;i++)g[i]=read();
	for(RG int i=1,a,b;i<=m;i++){
		a=read();b=read();a=find(a);b=find(b);
		num++;fa[a]=fa[b]=num;add(num,a);add(num,b);
	}
	for(RG int i=1;i<=n+n;i++)if(!fa[i])dfs(i,0);
	for(RG int i=1,a,b;i<=k;i++){
		a=read();b=read();if(find(a)!=find(b))continue;
		E[++t]=(edge){a,b,i,dep[lca(a,b)]};
	}
	sort(E+1,E+t+1,cmp);
	for(RG int i=1,s;i<=t;i++){
		s=min(g[E[i].u],g[E[i].v]);
		g[E[i].u]-=s;g[E[i].v]-=s;ans+=2ll*s;
	}
	printf("%lld\n",ans);
	return 0;
}

posted @ 2018-08-20 16:01  cjfdf  阅读(214)  评论(0编辑  收藏  举报