卧薪尝胆,厚积薄发。
BJOI2013 压力
Date: Mon Nov 05 15:47:31 CST 2018 In Category: NoCategory

Description:

给一个图和 $q$ 个传输要求,问每个点作为某个传输要求的必经点的次数。
$1\leqslant n\leqslant 10^5$

Solution:

发现必须经过的就是出发点所在的点双和结束点所在的点双之间的割点以及开始和结束点,那就求出这个图的点双连通分量并建立圆方树,那么树上这一条路径的所有圆点就是必经点,于是树上差分就可以了。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<stack>
#include<cctype>
#include<cstring>
using namespace std;
inline int rd()
{
register int res = 0,f = 1;
register char c = getchar();
while(!isdigit(c))
{
if(c == '-')f = -1;
c = getchar();
}
while(isdigit(c))
{
res = (res << 1) + (res << 3) + c - '0';
c = getchar();
}
return res * f;
}
int n,m,q;
#define MAXN 200010
struct edges
{
int u,v;
}es[MAXN << 1];
int cnte,cntp;
struct edge
{
int to,nxt;
}e[MAXN << 2];
int edgenum = 0;
int lin[MAXN] = {0};
void add(int a,int b)
{
e[++edgenum] = (edge){b,lin[a]};lin[a] = edgenum;
e[++edgenum] = (edge){a,lin[b]};lin[b] = edgenum;
return;
}
int dfn[MAXN],low[MAXN],tot = 0;
stack<int> s;
void tarjan(int k)
{
dfn[k] = low[k] = ++tot;
s.push(k);
for(int i = lin[k];i != 0;i = e[i].nxt)
{
if(dfn[e[i].to] == 0)
{
tarjan(e[i].to);
low[k] = min(low[k],low[e[i].to]);
if(low[e[i].to] >= dfn[k])
{
int t;
int p = ++cntp;
do
{
t = s.top();s.pop();
es[++cnte] = (edges){p,t};
}while(t != e[i].to);
es[++cnte] = (edges){p,k};
}
}
else low[k] = min(low[k],dfn[e[i].to]);
}
return;
}
int fa[MAXN],siz[MAXN],son[MAXN],top[MAXN],dep[MAXN],rnk[MAXN],th[MAXN];
void dfs1(int k,int depth)
{
dep[k] = depth;
siz[k] = 1;
for(int i = lin[k];i != 0;i = e[i].nxt)
{
if(e[i].to != fa[k])
{
fa[e[i].to] = k;
dfs1(e[i].to,depth + 1);
siz[k] += siz[e[i].to];
if(son[k] == 0 || siz[e[i].to] > siz[son[k]])
{
son[k] = e[i].to;
}
}
}
return;
}
void dfs2(int k,int tp)
{
top[k] = tp;
if(son[k] == 0)return;
dfs2(son[k],tp);
for(int i = lin[k];i != 0;i = e[i].nxt)
{
if(e[i].to != son[k] && e[i].to != fa[k])
{
dfs2(e[i].to,e[i].to);
}
}
return;
}
int LCA(int a,int b)
{
while(top[a] != top[b])
{
if(dep[top[a]] < dep[top[b]])swap(a,b);
a = fa[top[a]];
}
return (dep[a] < dep[b] ? a : b);
}
int val[MAXN];
bool v[MAXN];
void dfs(int k)
{
v[k] = true;
for(int i = lin[k];i != 0;i = e[i].nxt)
{
if(v[e[i].to])continue;
dfs(e[i].to);
val[k] += val[e[i].to];
}
return;
}
int main()
{
scanf("%d%d%d",&n,&m,&q);
int a,b;
for(int i = 1;i <= m;++i)
{
scanf("%d%d",&a,&b);
add(a,b);
}
cnte = 0;cntp = n;
for(int i = 1;i <= n;++i)
{
if(dfn[i] == 0)tarjan(i);
}
memset(lin,0,sizeof(lin));
edgenum = 0;
for(int i = 1;i <= cnte;++i)
{
add(es[i].u,es[i].v);
}
tot = 0;
dfs1(1,1);dfs2(1,1);
for(int i = 1;i <= q;++i)
{
a = rd();b = rd();
int lca = LCA(a,b);
++val[a];++val[b];
--val[lca];--val[fa[lca]];
}
dfs(1);
for(int i = 1;i <= n;++i)printf("%d\n",val[i]);
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡