bzoj3331 [BeiJing2013]压力 圆方树+树上差分

版权声明:虽然是个蒟蒻但是转载还是要说一声的哟 https://blog.csdn.net/jpwang8/article/details/83385416

Description


如今,路由器和交换机构建起了互联网的骨架。处在互联网的骨干位置的
核心路由器典型的要处理100Gbit/s的网络流量。他们每天都生活在巨大的压力
之下。
小强建立了一个模型。这世界上有N个网络设备,他们之间有M个双向的
链接。这个世界是连通的。在一段时间里,有Q个数据包要从一个网络设备发
送到另一个网络设备。
一个网络设备承受的压力有多大呢?很显然,这取决于Q个数据包各自走
的路径。不过,某些数据包无论走什么路径都不可避免的要通过某些网络设
备。
你要计算:对每个网络设备,必须通过(包括起点、终点)他的数据包有
多少个?

对于40%的数据,N,M,Q≤2000
对于60%的数据,N,M,Q≤40000
对于100%的数据,N≤100000,M,Q≤200000

Solution


一开始写了缩点发现这样不太好做。。
考虑建广义圆方树,路径上的必经点显然是树上路径中的圆点
由于做了很多天的树链剖分模拟赛已经吐了,我们今天用差分的做法。
对于一条路径修改(x,y),我们在x、y处+1,在lca和fa[lca]处-1,然后离线求和即可
好像没啥好说的。。。

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stack>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))

const int N=200005;

std:: stack <int> stack;

struct Graph {
	struct edge {int y,next;} e[N*2];
	int ls[N],edCnt;

	Graph() {fill(ls,0); edCnt=1;}
	edge operator [](int x) const {
		return e[x];
	}

	void add_edge(int x,int y) {
		e[++edCnt]=(edge) {y,ls[x]}; ls[x]=edCnt;
		e[++edCnt]=(edge) {x,ls[y]}; ls[y]=edCnt;
	}
} G,T;

int bl[N],size[N],fa[N],dep[N];
int dfn[N],low[N];
int s[N],tot;

bool vis[N];

int read() {
	int x=0,v=1; char ch=getchar();
	for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
	for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
	return x*v;
}

void dfs(int now,int from) {
	dfn[now]=low[now]=++dfn[0]; vis[now]=true;
	for (int i=G.ls[now];i;i=G[i].next) {
		if ((i^1)==from) continue;
		if (!dfn[G[i].y]) {
			stack.push(i); dfs(G[i].y,i);
			low[now]=std:: min(low[now],low[G[i].y]);
			if (dfn[now]<=low[G[i].y]) {
				int y=0; tot++;
				while (y!=i) {
					y=stack.top(); stack.pop();
					T.add_edge(tot,G[y].y);
				}
				T.add_edge(now,tot);
			}
		} else if (vis[G[i].y]) low[now]=std:: min(low[now],dfn[G[i].y]);
	}
	vis[now]=false;
}

void dfs1(int now) {
	size[now]=1;
	for (int i=T.ls[now];i;i=T[i].next) {
		if (T[i].y==fa[now]) continue;
		fa[T[i].y]=now; dep[T[i].y]=dep[now]+1;
		dfs1(T[i].y);
		size[now]+=size[T[i].y];
	}
}

void dfs2(int now,int up) {
	bl[now]=up; int mx=0;
	for (int i=T.ls[now];i;i=T[i].next) {
		if (T[i].y!=fa[now]&&size[T[i].y]>size[mx]) mx=T[i].y;
	}
	if (!mx) return ;
	dfs2(mx,up);
	for (int i=T.ls[now];i;i=T[i].next) {
		if (T[i].y!=fa[now]&&T[i].y!=mx) dfs2(T[i].y,T[i].y);
	}
}

int get_lca(int x,int y) {
	for (;bl[x]!=bl[y];) {
		(dep[bl[x]]<dep[bl[y]])?(std:: swap(x,y)):(void)0;
		x=fa[bl[x]];
	}
	return dep[x]<dep[y]?x:y;
}

void dfs3(int now) {
	for (int i=T.ls[now];i;i=T[i].next) {
		if (T[i].y==fa[now]) continue;
		dfs3(T[i].y);
		s[now]+=s[T[i].y];
	}
}

int main(void) {
	int n=read(),m=read(),q=read(); tot=n;
	rep(i,1,m) G.add_edge(read(),read());
	dfs(1,0);
	dfs1(1); dfs2(1,1);
	rep(i,1,q) {
		int x=read(),y=read();
		int lca=get_lca(x,y);
		s[x]++; s[y]++;
		s[lca]--; s[fa[lca]]--;
	}
	dfs3(1);
	rep(i,1,n) printf("%d\n", s[i]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/83385416