[题解]gdfzoj 902

边双+LCA

code

#include<bits/stdc++.h>
namespace my_std
{
	using namespace std;
	#define rep(i,a,b) for (int i=(a);i<=(b);i++)
	#define drep(i,a,b) for (int i=(a);i>=(b);i--)
	#define go(u) for (int i=head[(u)];i;i=e[i].nxt)
	#define pf printf
	#define writeln(x) write(x),putchar('\n')
	#define writesp(x) write(x),putchar(' ')
	#define mem(x,v) memset(x,v,sizeof(x))
	typedef long long ll;
	const int INF=0x7fffffff;
	inline int read()
	{
		int sum=0,f=1;
		char c=0;
		while (!isdigit(c))
		{
			if (c=='-') f=-1;
			c=getchar();
		}
		while (isdigit(c))
		{
			sum=(sum<<1)+(sum<<3)+(c^48);
			c=getchar();
		}
		return sum*f;
	}
	void write(int k)
	{
		if (k<0) putchar('-'),k=-k;
		if (k>=10) write(k/10);
		putchar(k%10+'0');
	}
}
using namespace my_std;
const int N=100010;
const int M=500010;
int n,m,quiz;
int cnt1,cnt2=1,head[N],HEAD[N];
int idx,low[N],dfn[N];
int col,color[N],sum[N],val[N];
int sum_plus[N];
int dep[N],f[N][21];
bool bridge[M<<1];
struct edge
{
	int to,nxt;
}e[M<<1],E[M<<1];
void add1(int u,int v)
{
	e[++cnt1].to=v;
	e[cnt1].nxt=head[u];
	head[u]=cnt1;
}
void add2(int u,int v)
{
	E[++cnt2].to=v;
	E[cnt2].nxt=HEAD[u];
	HEAD[u]=cnt2;
}
void tarjan(int u,int last)
{
	low[u]=dfn[u]=++idx;
	for (int i=HEAD[u];i;i=E[i].nxt)
	{
		int v=E[i].to;
		if (!dfn[v])
		{
			tarjan(v,i);
			low[u]=min(low[u],low[v]);
			if (low[v]>dfn[u])
			{
				bridge[i]=1;
				bridge[i^1]=1;
			}
		}
		else if (i!=(last^1)) low[u]=min(low[u],dfn[v]);
	}
}
void get_color(int u,int r)
{
	color[u]=r;
	sum[color[u]]+=val[u];
	for (int i=HEAD[u];i;i=E[i].nxt)
	{
		int v=E[i].to;
		if (!color[v]&&!bridge[i])
		{
			get_color(v,r);
		}
	}
}
void build_tree()
{
	rep(u,1,n)
	{
		for (int i=HEAD[u];i;i=E[i].nxt)
		{
			int v=E[i].to;
			if (bridge[i])
			{
				add1(color[u],color[v]);
			}
		}
	}
}
void dfs(int u,int fa)
{
	dep[u]=dep[fa]+1;
	f[u][0]=fa;
	for (int i=1;(1<<i)<=dep[u];i++)
	{
		f[u][i]=f[f[u][i-1]][i-1];
	}
	go(u)
	{
		int v=e[i].to;
		if (v==fa) continue;
		dfs(v,u);
	}
}
int lca(int x,int y)
{
	if (dep[x]<dep[y]) swap(x,y);
	drep(i,20,0)
	{
		if (dep[f[x][i]]>=dep[y]) x=f[x][i];
		if (x==y) return x;
	}
	drep(i,20,0)
	{
		if (f[x][i]!=f[y][i])
		{
			x=f[x][i];
			y=f[y][i];
		}
	}
	return f[x][0];
}
void getsum(int u,int fa)
{
	sum_plus[u]=sum_plus[fa]+sum[u];
	go(u)
	{
		int v=e[i].to;
		if (v==fa) continue;
		getsum(v,u);
	}
}
int solve(int u,int v)
{
	if (color[u]==color[v]) return sum[color[u]];
	int LCA=lca(color[u],color[v]);
	int ans=sum_plus[color[u]]+sum_plus[color[v]]-sum_plus[LCA]-sum_plus[f[LCA][0]];
	return ans;
}
int main()
{
	n=read(),m=read();quiz=read();
	rep(i,1,n) val[i]=read();
	int u,v;
	rep(i,1,m)
	{
		u=read(),v=read();
		add2(u,v),add2(v,u);
	}
	tarjan(1,-INF);
	rep(i,1,n) if (!color[i]) get_color(i,++col);
	build_tree();
	dfs(color[1],0);
	getsum(color[1],0);
	rep(i,1,quiz)
	{
		u=read(),v=read();
		writeln(solve(u,v));
	}
}

进阶版:BZOJ 2959

posted @ 2020-03-05 15:32  ZSH_ZSH  阅读(126)  评论(0编辑  收藏  举报