BZOJ 3331压力

14 篇文章 0 订阅
3 篇文章 0 订阅

【问题描述】

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

【输入】

第一行包含3个由空格隔开的正整数N,M,Q。
接下来M行,每行两个整数u,v,表示第u个网络设备(从1开始编号)和第v个网络设备之间有一个链接。u不会等于v。两个网络设备之间可能有多个链接。
接下来Q行,每行两个整数p,q,表示第p个网络设备向第q个网络设备发送了一个数据包。p不会等于q。

【输

输出N行,每行1个整数,表示必须通过某个网络设备的数据包的数量。

样例输入】

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

样例

2
1
1
2

【数据范围与约定】

样例解释:
设备1、2、3之间两两有链接,4只和1有链接。4想向2和3各发送一个数据包。显然,这两个数据包必须要经过它的起点、终点和1。

数据规模:
对于40%的数据,1<=N,M,Q<=2000
对于60%的数据,1<=N,M,Q<=40000
对于100%的数据,1<=N<=100000,1<=M,Q<=200000

一眼题。求出点双之后成为一棵树,用各种方法乱搞。

主要是太久没写点双= =

#include<bits/stdc++.h>
using namespace std;
inline int get(){register int re=0,f=1;register char c;while(c=getchar(),(c>='0'&&c<='9')^1)f=c^'-';while(re=(re<<1)+(re<<3)+(c^48),c=getchar(),(c>='0'&&c<='9'));return f?re:-re;}
const int Maxn=400005;
vector<int>G[Maxn];
int n,m,q;
struct Splay{
	int p[Maxn],ch[2][Maxn];
	bool rev[Maxn];
	int v[Maxn],tag[Maxn];
	#define ls(x) ch[0][x]
	#define rs(x) ch[1][x]
	inline bool isroot(int x){
		return (ls(p[x])^x)&&(rs(p[x])^x);
	}
	inline void rotate(int x){
		int f=p[x],gf=p[f],tp=rs(f)==x,son=ch[!tp][x];
		if(!isroot(f))ch[rs(gf)==f][gf]=x;p[x]=gf;
		ch[tp][p[son]=f]=son;
		ch[!tp][p[f]=x]=f;
	}
	inline void pushdown(int x){
		if(rev[x]){
			rev[ls(x)]^=1,rev[rs(x)]^=1;
			swap(ls(x),rs(x));
			rev[x]^=1;
		}
		if(tag[x]){
			v[ls(x)]+=tag[x];v[rs(x)]+=tag[x];
			tag[ls(x)]+=tag[x],tag[rs(x)]+=tag[x];
			tag[x]=0;
		}
	}
	int top,s[Maxn];
	inline void splay(int x){
		s[++top]=x;for(int i=x;!isroot(i);i=p[i])s[++top]=p[i];
		while(top)pushdown(s[top--]);
		while(!isroot(x)){
			if(!isroot(p[x])&&((rs(p[p[x]])==p[x])==(rs(p[x])==x)))rotate(p[x]);
			rotate(x);
		}
	}
};
struct LinkcutTree{
	Splay splay;
	inline void access(int x){
		for(int lastx=0;x;lastx=x,x=splay.p[x])
			splay.splay(x),splay.rs(x)=lastx;
	}
	inline void makeroot(int x){
		access(x),splay.splay(x),splay.rev[x]^=1;
	}
	inline void link(int x,int y){
		makeroot(x),splay.p[x]=y;
	}
	inline void split(int x,int y){
		makeroot(x),access(y),splay.splay(y);
	}
}lct;
struct Targan{
	int cnt,tj[Maxn],ll[Maxn];
	int bcc,top,s[Maxn];
	void Tarjan(int x,int fa){
		tj[x]=ll[x]=++cnt;
		s[++top]=x;
		for(int i=0;i<G[x].size();++i){
			int to=G[x][i];if(to==fa)continue;
			if(!tj[to]){
				Tarjan(to,x);
				ll[x]=min(ll[x],ll[to]);
				if(ll[to]>=tj[x]){
					++bcc;int v;
					do{
						v=s[top--];
//						cout<<n+bcc<<" "<<v<<"\n";
						lct.link(n+bcc,v);
					}while(v^to);
//					cout<<n+bcc<<" "<<x<<"\n";
					lct.link(n+bcc,x);
				}
			}else ll[x]=min(ll[x],tj[to]);
		}
	}
}targan;
int main(){
	freopen("pressure.in","r",stdin);
	freopen("pressure.out","w",stdout);
	n=get(),m=get(),q=get();
	for(int i=1;i<=m;++i){
		int x=get(),y=get();
		G[x].push_back(y);
		G[y].push_back(x);
	}
	for(int i=1;i<=n;++i)
		if(!targan.tj[i])targan.Tarjan(i,0);
	while(q--){
		int x=get(),y=get();
		lct.split(x,y);
		++lct.splay.v[y];
		++lct.splay.tag[y];
	}
	for(int i=1;i<=n;++i){
		lct.makeroot(i);
		cout<<lct.splay.v[i]<<"\n";
	}
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值