【问题描述】
如今,路由器和交换机构建起了互联网的骨架。处在互联网的骨干位置的核心路由器典型的要处理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;
}