压力
题目描述
如今,路由器和交换机构建起了互联网的骨架。处在互联网的骨干位置的核心路由器典型的要处理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%的数据,N,M,Q≤2000
对于60%的数据,N,M,Q≤40000
对于100%的数据,N≤100000,M,Q≤200000
通过打这个题,我知道了自己码力有多么弱。
首先如果路径上有割点一定是必经点,然后如果是环上的点(除了割点)一定有多条路径可以到,所以环上(除了割点起点终点)都不必经。
所以点双缩点,重新建图(普通建图or圆方)
那么对于每组询问lca加普通树差标记一下,
对于每组询问拿数组zz记录起点终点,
最后dfs扫一遍
,结束时如果不为割点,直接输出zz
否则输出dfs扫出的ans
没什么好说的。
必经点模版题


#include<bits/stdc++.h> #define ll long long #define pt printf("******\n") #define A 1000000 using namespace std; ll tot=0,head[A],sta[A],low[A],dfn[A],nxt[A],ver[A],deep[A],belong[A],cut[A]; ll tc=0,head_c[A],nxt_c[A],ver_c[A],sz[A],f[A][30],ans[A],zz[A]; ll n,m,q,t,num=0,cnt=0,root,top=0; vector<ll> scc[A]; bool flag[A],vis[A]; void add(ll x,ll y){ nxt[++tot]=head[x],head[x]=tot,ver[tot]=y; } void add_c(ll x,ll y){ nxt_c[++tc]=head_c[x],head_c[x]=tc,ver_c[tc]=y; } void tarjan(ll x){ low[x]=dfn[x]=++num; sta[++top]=x;ll vis=0; if(x==root&&!head[x]) { cnt++; belong[x]=cnt; scc[cnt].push_back(x); } for(ll i=head[x];i;i=nxt[i]){ ll y=ver[i]; if(!dfn[y]){ tarjan(y); low[x]=min(low[x],low[y]); if(dfn[x]<=low[y]){ vis++; if(x!=root||vis>1) cut[x]=1; cnt++; ll z; do{ z=sta[top--]; belong[z]=cnt; scc[cnt].push_back(z); }while(z!=y); belong[x]=cnt; scc[cnt].push_back(x); } } else low[x]=min(low[x],dfn[y]); } } inline ll lca(ll x,ll y){ if(deep[x]>deep[y]) swap(x,y); ll w; for(w=0;(1<<w)<=deep[y];w++); w--; for(ll i=w;i>=0;i--) { // printf("deep[%lld]=%lld deep[%lld]=%lld f[%lld]=%lld\n",x,deep[x],y,deep[y],i,f[y][i]); if(deep[x]<=deep[f[y][i]]) y=f[y][i]; if(deep[x]==deep[y]) break; } if(x==y) return x; for(ll i=w;i>=0;i--){ if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; } return f[y][0]; } void dfs2(ll x,ll de){ deep[x]=de;flag[x]=1; for(ll i=head_c[x];i;i=nxt_c[i]){ ll y=ver_c[i]; if(flag[y]) continue; f[y][0]=x; dfs2(y,de+1); } } ll dfs3(ll x){ vis[x]=1; for(ll i=head_c[x];i;i=nxt_c[i]){ ll y=ver_c[i]; if(vis[y]) continue; ll to=dfs3(y); ans[x]+=to; } return ans[x]; } int main(){ // freopen("mkd.txt","r",stdin); // freopen("wa.txt","w",stdout); scanf("%lld%lld%lld",&n,&m,&q); t=log(n)/log(2)+5; for(ll i=1;i<=m;i++){ ll x,y; scanf("%lld%lld",&x,&y); add(x,y);add(y,x); } for(ll i=1;i<=n;i++){ if(!dfn[i]) root=i,tarjan(i); } num=cnt; for(ll i=1;i<=n;i++) if(cut[i]) belong[i]=++num/*,printf("gd=%lld\n",i)*/; for(ll i=1;i<=cnt;i++){ ll size=scc[i].size(); for(ll j=0;j<size;j++){ if(cut[scc[i][j]]){ add_c(i,belong[scc[i][j]]); add_c(belong[scc[i][j]],i); } } } dfs2(1,1),f[1][0]=1; for(ll j=1;j<=t;j++) for(ll i=1;i<=num;i++) f[i][j]=f[f[i][j-1]][j-1]; /*for(ll i=1;i<=n;i++){ printf("belong=%lld\n",belong[i]); } for(ll i=1;i<=num;i++) { printf("deep[i]=%lld f[i][0]=%lld belong=%lld\n",deep[belong[i]],f[belong[i]][0],belong[i]); }*/ for(ll i=1;i<=q;i++){ ll x,y; scanf("%lld%lld",&x,&y); ll lc=lca(belong[x],belong[y]); // cout<<lc<<endl; zz[x]++,zz[y]++; // printf("x=%lld y=%lld lc=%lld lf=%lld\n",belong[x],belong[y],lc,f[lc][0]); ans[belong[x]]++; ans[belong[y]]++; ans[lc]--; if(f[lc][0]!=lc)ans[f[lc][0]]--; } dfs3(1); for(ll i=1;i<=n;i++){ if(cut[i]) cout<<ans[belong[i]]<<endl; else cout<<zz[i]<<endl; } return 0; }